SB & PB JSON-RPC CGI
Posted: Thu Jul 18, 2019 5:48 pm
As there are a few forum members struggling to get started with PureBasic's CGI commands I have quickly put together a simple PureBasic JSON-RPC CGI that exposes one method (sayhello) and an equally simple SpiderBasic client that calls the method and displays the response in the debug window:
PureBasic
Compile this as cgitest.cgi and place that in the "cgi-bin" subfolder of your website (remember to match the architecture of your server).
SpiderBasic
You have to compile this (Enable Debugger should be ticked) and serve it from the same server that's hosting the CGI
PureBasic
Compile this as cgitest.cgi and place that in the "cgi-bin" subfolder of your website (remember to match the architecture of your server).
Code: Select all
Declare SayHello(jsParams,jsRO)
Declare SendChunk(txt$)
Procedure FormatError(jsRO,errcode,errmsg$)
jsErr = AddJSONMember(jsRO,"error")
jsErrO = SetJSONObject(jsErr)
SetJSONString(AddJSONMember(jsErrO,"message"),errmsg$)
SetJSONInteger(AddJSONMember(jsErrO,"code"),errcode)
SetJSONInteger(AddJSONMember(jsErrO,"origin"),2)
jsResP = AddJSONMember(jsRO,"result")
SetJSONNull(jsResp)
EndProcedure
Procedure ProcessIncoming(incoming$)
jsRP = CreateJSON(#PB_Any) ; Start building our JSON-RPC response
jsRO = SetJSONObject(JSONValue(jsRP))
WriteCGIString("Content-type: application/json" + #CRLF$,#PB_UTF8)
WriteCGIString("Transfer-Encoding: chunked" + #CRLF$ + #CRLF$,#PB_UTF8)
js = ParseJSON(#PB_Any,incoming$) ; Parse incoming JSON-RPC
; details here: https://en.wikipedia.org/wiki/JSON-RPC
If js
todo$ = GetJSONString(GetJSONMember(JSONValue(js),"method"))
id$ = GetJSONString(GetJSONMember(JSONValue(js),"id"))
jsParams = GetJSONMember(JSONValue(js),"params")
SetJSONString(AddJSONMember(jsRO,"id"),id$) ; always return id
Select todo$ ; route and pass params to requested method
Case "sayhello"
SayHello(jsParams,jsRO)
Default
FormatError(jsRO,4,"Method not found: "+todo$)
EndSelect
SendChunk(ComposeJSON(jsRP,#PB_JSON_PrettyPrint))
FreeJSON(js)
FreeJSON(jsRP)
EndIf
EndProcedure
Procedure SayHello(jsParams,jsRO)
NewMap qp.s()
ExtractJSONMap(jsParams,qp())
jsErr = AddJSONMember(jsRO,"error")
SetJSONNull(jsErr)
jsResP = AddJSONMember(jsRO,"result")
jsResO = SetJSONObject(jsResP)
SetJSONString(AddJSONMember(jsResO,"msg"),qp("recipient") + " said: '" + qp("greeting") + "'")
EndProcedure
Procedure SendChunk(txt$)
nSize = StringByteLength(txt$,#PB_UTF8)
If nSize = 0 : ProcedureReturn : EndIf ; don't want to SendEOT by mistake
hxSize$ = Hex(nSize)
res$ = hxSize$ + #CRLF$ + txt$ + #CRLF$
WriteCGIString(res$,#PB_UTF8)
EndProcedure
Procedure SendEOT()
WriteCGIString(Hex(0) + #CRLF$ + #CRLF$,#PB_UTF8)
EndProcedure
If Not InitCGI() : End : EndIf
BufferSize = ReadCGI()
If BufferSize = 0 : End : EndIf
RequestBody$ = PeekS(CGIBuffer(),BufferSize,#PB_UTF8)
ProcessIncoming(RequestBody$)
SendEOT()
You have to compile this (Enable Debugger should be ticked) and serve it from the same server that's hosting the CGI
Code: Select all
request$ = ""
Procedure HttpGetEvent(Success,Result$,UserData)
If Success
Debug Result$
Else
Debug "HTTPRequest(): Error"
EndIf
EndProcedure
If CreateJSON(0)
jso = SetJSONObject(JSONValue(0))
SetJSONString(AddJSONMember(jso,"method"),"sayhello")
SetJSONString(AddJSONMember(jso,"id"),"abc123")
jsp = SetJSONObject(AddJSONMember(jso,"params"))
SetJSONString(AddJSONMember(jsp,"recipient"),"Weave")
SetJSONString(AddJSONMember(jsp,"greeting"),"Hello, World!")
request$ = ComposeJSON(0)
FreeJSON(0)
EndIf
Debug request$
Debug ""
NewMap Headers$()
Headers$("Content-Type") = "application/json"
HTTPRequest(#PB_HTTP_Post,"cgi-bin/cgitest.cgi",request$,@HttpGetEvent(),0,Headers$())