├── .gitignore
├── Examples
├── 6) Returning nested JSON.au3
├── 8) Return other status codes.au3
├── 9) Get route request param data.au3
├── 7) Returning Text or Html instead of Json.au3
├── 1) Most basic setup.au3
├── 2) Set name, version and description of your API.au3
├── 3) Your first route.au3
├── 4) Get route request data.au3
└── 5) Get route header data.au3
├── Testing
├── Tests
│ ├── Most basic.au3
│ ├── Basic response types.au3
│ ├── Request data.au3
│ ├── Route params.au3
│ └── TestApp.au3
└── TestSuite.au3
├── docs
├── refs
│ ├── _API_GetUDFVer.html
│ ├── _API_MGR_Init.html
│ ├── _API_MGR_SetName.html
│ ├── _API_MGR_SetVer.html
│ ├── _API_MGR_SetDescription.html
│ ├── _API_RES_NotFound.html
│ ├── _API_MGR_ROUTER_EndPrefix.html
│ ├── _API_MGR_ROUTER_HANDLE.html
│ ├── _API_MGR_ROUTER_GET.html
│ ├── _API_MGR_ROUTER_PUT.html
│ ├── _API_MGR_ROUTER_POST.html
│ ├── _API_MGR_ROUTER_PATCH.html
│ ├── _API_MGR_ROUTER_DELETE.html
│ ├── _API_RES_InternalServerError.html
│ ├── _API_RES_INTERNAL_SERVER_ERROR.html
│ ├── _API_RES_SET_CONTENT_TYPE.html
│ ├── _API_RES_SET_STATUS.html
│ ├── _API_MGR_ROUTER_ANY.html
│ ├── _API_RES_BadRequest.html
│ ├── _API_MGR_ROUTER_Prefix.html
│ ├── _API_MGR_ROUTER_Register.html
│ └── style.css
└── index.html
├── generateDocs.au3
├── README.md
├── Testing.au3
└── API.au3
/.gitignore:
--------------------------------------------------------------------------------
1 | BackUp/
2 | *.exe
3 | test.au3
--------------------------------------------------------------------------------
/Examples/6) Returning nested JSON.au3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tarreislam/Autoit-API-WS/HEAD/Examples/6) Returning nested JSON.au3
--------------------------------------------------------------------------------
/Examples/8) Return other status codes.au3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tarreislam/Autoit-API-WS/HEAD/Examples/8) Return other status codes.au3
--------------------------------------------------------------------------------
/Examples/9) Get route request param data.au3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tarreislam/Autoit-API-WS/HEAD/Examples/9) Get route request param data.au3
--------------------------------------------------------------------------------
/Examples/7) Returning Text or Html instead of Json.au3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tarreislam/Autoit-API-WS/HEAD/Examples/7) Returning Text or Html instead of Json.au3
--------------------------------------------------------------------------------
/Testing/Tests/Most basic.au3:
--------------------------------------------------------------------------------
1 | #include "../../API.AU3"
2 |
3 |
4 | ; Init the _API manager
5 | _API_MGR_Init(4545)
6 | If @error Then Exit(1)
7 |
8 |
9 | ; Handle requests
10 | While _API_MGR_ROUTER_HANDLE()
11 | WEnd
12 |
--------------------------------------------------------------------------------
/Examples/1) Most basic setup.au3:
--------------------------------------------------------------------------------
1 | #include "../API.AU3"
2 |
3 |
4 | ; Init the _API manager
5 | _API_MGR_Init(4545)
6 | If @error Then
7 | MsgBox(64,"", "Failed to init API. Error " & @error)
8 | Exit
9 | EndIf
10 |
11 |
12 |
13 | ; Handle requests
14 | While _API_MGR_ROUTER_HANDLE()
15 | WEnd
16 |
--------------------------------------------------------------------------------
/Testing/Tests/Basic response types.au3:
--------------------------------------------------------------------------------
1 | #include "../../API.AU3"
2 |
3 |
4 | ; Init the _API manager
5 | _API_MGR_Init(4545)
6 | If @error Then Exit(1)
7 |
8 | _API_MGR_ROUTER_ANY('/test', CB_Test)
9 |
10 |
11 | ; Handle requests
12 | While _API_MGR_ROUTER_HANDLE()
13 | WEnd
14 |
15 | Func CB_Test()
16 |
17 | Return 'OK'
18 | EndFunc
--------------------------------------------------------------------------------
/Testing/Tests/Request data.au3:
--------------------------------------------------------------------------------
1 | #include "../../API.AU3"
2 |
3 |
4 | ; Init the _API manager
5 | _API_MGR_Init(4545)
6 | If @error Then Exit(1)
7 |
8 | _API_MGR_ROUTER_GET('/test', CB_Test)
9 |
10 |
11 | ; Handle requests
12 | While _API_MGR_ROUTER_HANDLE()
13 | WEnd
14 |
15 | Func CB_Test(Const $oRequest)
16 |
17 |
18 |
19 | ; Pass the object back to our router, which will convert it into escaped json
20 | Return $oRequest
21 | EndFunc
--------------------------------------------------------------------------------
/Testing/Tests/Route params.au3:
--------------------------------------------------------------------------------
1 | #include "../../API.AU3"
2 |
3 |
4 | ; Init the _API manager
5 | _API_MGR_Init(4545)
6 | If @error Then Exit(1)
7 |
8 | _API_MGR_ROUTER_GET('/test/{mypath}', CB_Test)
9 |
10 |
11 | ; Handle requests
12 | While _API_MGR_ROUTER_HANDLE()
13 | WEnd
14 |
15 | Func CB_Test(Const $oRequest)
16 |
17 |
18 |
19 | ; Pass the object back to our router, which will convert it into escaped json
20 | Return $oRequest
21 | EndFunc
--------------------------------------------------------------------------------
/docs/refs/_API_GetUDFVer.html:
--------------------------------------------------------------------------------
1 |
Function _API_GetUDFVer _API_GetUDFVer Get the semantic version of the UDF
Return Value Remarks See more on semver @ http://semver.org/
Related
--------------------------------------------------------------------------------
/docs/refs/_API_MGR_Init.html:
--------------------------------------------------------------------------------
1 | Function _API_MGR_Init _API_MGR_Init Initializes the API and starts listening on the given port. Default is 8080
Return Value Remarks
Related _API_MGR_ROUTER_HANDLE
--------------------------------------------------------------------------------
/docs/refs/_API_MGR_SetName.html:
--------------------------------------------------------------------------------
1 | Function _API_MGR_SetName _API_MGR_SetName Set the name of your API (Not parsed, just for docs)
Return Value Remarks
Related _API_MGR_SetVer , _API_MGR_SetDescription
--------------------------------------------------------------------------------
/docs/refs/_API_MGR_SetVer.html:
--------------------------------------------------------------------------------
1 | Function _API_MGR_SetVer _API_MGR_SetVer Set the version of your API (Not parsed, just for docs)
Return Value Remarks
Related _API_MGR_SetName , _API_MGR_SetDescription
--------------------------------------------------------------------------------
/docs/refs/_API_MGR_SetDescription.html:
--------------------------------------------------------------------------------
1 | Function _API_MGR_SetDescription _API_MGR_SetDescription Set the description of your API (Not parsed, just for docs)
Return Value Remarks
Related _API_MGR_SetVer , _API_MGR_SetName
--------------------------------------------------------------------------------
/Examples/2) Set name, version and description of your API.au3:
--------------------------------------------------------------------------------
1 | ; Include the UDF
2 | #include "../API.au3"
3 |
4 | ; Set basic app info
5 | _API_MGR_SetName("My APP adapter")
6 | _API_MGR_SetVer("1.0 BETA")
7 | _API_MGR_SetDescription("This adapter wraps some stuff from my app")
8 |
9 | ; Init the _API manager
10 | _API_MGR_Init(4545)
11 | If @error Then
12 | MsgBox(64,"", "Failed to init API. Error " & @error)
13 | Exit
14 | EndIf
15 |
16 | ; Success
17 | ConsoleWrite("Please visit http://localhost:4545" & @LF)
18 |
19 | ; Handle requests
20 | While _API_MGR_ROUTER_HANDLE()
21 | WEnd
--------------------------------------------------------------------------------
/docs/refs/_API_RES_NotFound.html:
--------------------------------------------------------------------------------
1 | Function _API_RES_NotFound _API_RES_NotFound Shorthend for "API_RES_BadRequest" that only takes 1 params instead of two
Return Value Remarks
Related _API_RES_BadRequest , _API_RES_InternalServerError
--------------------------------------------------------------------------------
/docs/refs/_API_MGR_ROUTER_EndPrefix.html:
--------------------------------------------------------------------------------
1 | Function _API_MGR_ROUTER_EndPrefix _API_MGR_ROUTER_EndPrefix Removes the prefix for the following router registrations
Return Value Remarks $sDummy can be used to give a visual representation, it will not be parsed
Related _API_MGR_ROUTER_Prefix
--------------------------------------------------------------------------------
/docs/refs/_API_MGR_ROUTER_HANDLE.html:
--------------------------------------------------------------------------------
1 | Function _API_MGR_ROUTER_HANDLE _API_MGR_ROUTER_HANDLE This function handles all incoming requests. This Should be used in your applications mainloop
Return Value Remarks This should be called at least every 100 ms
Related _API_MGR_INIT
--------------------------------------------------------------------------------
/docs/refs/_API_MGR_ROUTER_GET.html:
--------------------------------------------------------------------------------
1 | Function _API_MGR_ROUTER_GET _API_MGR_ROUTER_GET Shorthand for _API_MGR_ROUTER_Register
Return Value Remarks Read more at _API_MGR_ROUTER_Register
Related _API_MGR_ROUTER_Register
--------------------------------------------------------------------------------
/docs/refs/_API_MGR_ROUTER_PUT.html:
--------------------------------------------------------------------------------
1 | Function _API_MGR_ROUTER_PUT _API_MGR_ROUTER_PUT Shorthand for _API_MGR_ROUTER_Register
Return Value Remarks Read more at _API_MGR_ROUTER_Register
Related _API_MGR_ROUTER_Register
--------------------------------------------------------------------------------
/docs/refs/_API_MGR_ROUTER_POST.html:
--------------------------------------------------------------------------------
1 | Function _API_MGR_ROUTER_POST _API_MGR_ROUTER_POST Shorthand for _API_MGR_ROUTER_Register
Return Value Remarks Read more at _API_MGR_ROUTER_Register
Related _API_MGR_ROUTER_Register
--------------------------------------------------------------------------------
/docs/refs/_API_MGR_ROUTER_PATCH.html:
--------------------------------------------------------------------------------
1 | Function _API_MGR_ROUTER_PATCH _API_MGR_ROUTER_PATCH Shorthand for _API_MGR_ROUTER_Register
Return Value Remarks Read more at _API_MGR_ROUTER_Register
Related _API_MGR_ROUTER_Register
--------------------------------------------------------------------------------
/docs/refs/_API_MGR_ROUTER_DELETE.html:
--------------------------------------------------------------------------------
1 | Function _API_MGR_ROUTER_DELETE _API_MGR_ROUTER_DELETE Shorthand for _API_MGR_ROUTER_Register
Return Value Remarks Read more at _API_MGR_ROUTER_Register
Related _API_MGR_ROUTER_Register
--------------------------------------------------------------------------------
/docs/refs/_API_RES_InternalServerError.html:
--------------------------------------------------------------------------------
1 | Function _API_RES_InternalServerError _API_RES_InternalServerError Shorthend for "API_RES_BadRequest" that only takes 1 params instead of two
Return Value Remarks
Related _API_RES_BadRequest , _API_RES_NotFound
--------------------------------------------------------------------------------
/docs/refs/_API_RES_INTERNAL_SERVER_ERROR.html:
--------------------------------------------------------------------------------
1 | Function _API_RES_INTERNAL_SERVER_ERROR _API_RES_INTERNAL_SERVER_ERROR Shorthend for "API_RES_BadRequest" that only takes 1 params instead of two
Return Value Remarks
Related _API_RES_BadRequest , _API_RES_NotFound
--------------------------------------------------------------------------------
/docs/refs/_API_RES_SET_CONTENT_TYPE.html:
--------------------------------------------------------------------------------
1 | Function _API_RES_SET_CONTENT_TYPE _API_RES_SET_CONTENT_TYPE Set the content type of your request. The default value after each request is $API_CONTENT_TYPE_TEXTJSON
Return Value Remarks The most common statuses are defined as constants, see more at #Region Mimes (Content types)
Related _API_RES_SET_STATUS
--------------------------------------------------------------------------------
/docs/refs/_API_RES_SET_STATUS.html:
--------------------------------------------------------------------------------
1 | Function _API_RES_SET_STATUS _API_RES_SET_STATUS Set the response status code and text for your response. The default value after each request is $API_STATUS_OK
Return Value Remarks The most common statuses are defined as constants, see more at #Region Respons statuses
Related _API_RES_SET_CONTENT_TYPE
--------------------------------------------------------------------------------
/docs/refs/_API_MGR_ROUTER_ANY.html:
--------------------------------------------------------------------------------
1 | Function _API_MGR_ROUTER_ANY _API_MGR_ROUTER_ANY Shorthand for _API_MGR_ROUTER_Register
Return Value Remarks This will register the most common route methods. Read more at _API_MGR_ROUTER_Register
Related _API_MGR_ROUTER_Register
--------------------------------------------------------------------------------
/docs/refs/_API_RES_BadRequest.html:
--------------------------------------------------------------------------------
1 | Function _API_RES_BadRequest _API_RES_BadRequest Shorthend function for a "bad request" response
Return Value Remarks The json will always return with this structure: {"description": "Custom message descrpition"} with the given status code
Related _API_RES_NotFound , _API_RES_InternalServerError
--------------------------------------------------------------------------------
/docs/refs/_API_MGR_ROUTER_Prefix.html:
--------------------------------------------------------------------------------
1 | Function _API_MGR_ROUTER_Prefix _API_MGR_ROUTER_Prefix Sets a given prefix to the following router registrations.
Return Value Remarks
Related _API_MGR_ROUTER_EndPrefix , _API_MGR_ROUTER_HANDLE , _API_MGR_ROUTER_Register , _API_MGR_ROUTER_GET , _API_MGR_ROUTER_POST , _API_MGR_ROUTER_PUT , _API_MGR_ROUTER_PATCH , _API_MGR_ROUTER_DELETE
--------------------------------------------------------------------------------
/Examples/3) Your first route.au3:
--------------------------------------------------------------------------------
1 | ; Include the UDF
2 | #include "../API.au3"
3 |
4 | ; Set basic app info
5 | _API_MGR_SetName("My APP adapter")
6 | _API_MGR_SetVer("1.0 BETA")
7 | _API_MGR_SetDescription("This adapter wraps some stuff from my app")
8 |
9 | ; Init the _API manager
10 | _API_MGR_Init(4545)
11 | If @error Then
12 | MsgBox(64,"", "Failed to init API. Error " & @error)
13 | Exit
14 | EndIf
15 |
16 | ; Register routes (Must be done after MGR_INIT)
17 | _API_MGR_ROUTER_GET('/my-first-route', _CB_MyFirstRoute)
18 |
19 | ; Success
20 | ConsoleWrite("Please visit http://localhost:4545" & @LF)
21 |
22 | ; Handle requests
23 | While _API_MGR_ROUTER_HANDLE()
24 | WEnd
25 |
26 | ; Define your routes here
27 |
28 | Func _CB_MyFirstRoute()
29 | ; This UDF relies on the Dictionary object to create JSON (See more here: https://docs.microsoft.com/en-us/office/vba/language/reference/user-interface-help/dictionary-object)
30 |
31 | ; Create an empty object
32 | Local $object = ObjCreate("Scripting.Dictionary")
33 |
34 | ; Assign some values
35 |
36 | $object.add('username', @UserName)
37 | $object.add('computerName', @ComputerName)
38 |
39 | ; Pass the object back to our router, which will convert it into escaped json
40 | Return $object
41 | EndFunc
--------------------------------------------------------------------------------
/docs/refs/_API_MGR_ROUTER_Register.html:
--------------------------------------------------------------------------------
1 | Function _API_MGR_ROUTER_Register _API_MGR_ROUTER_Register Register a HTTP route with a callback.
Return Value Remarks The $callback param CAN have 2, 1 or 0 (ZERO) params. Func MyCallback(Const $oRequest, Const, $oHeaders), Func MyCallback(Const $oRequest), Func MyCallback(). The $requiredParams has the following format "type Name<*required>" and is separated by pipelines, for example. "string name*" = "String $name (Required)", if <*> is not used, the result will be "String $name (Optional)"
Related _API_MGR_ROUTER_Prefix , _API_MGR_ROUTER_HANDLE , _API_MGR_ROUTER_GET , _API_MGR_ROUTER_POST , _API_MGR_ROUTER_PUT , _API_MGR_ROUTER_PATCH , _API_MGR_ROUTER_DELETE
--------------------------------------------------------------------------------
/Examples/4) Get route request data.au3:
--------------------------------------------------------------------------------
1 | ; Include the UDF
2 | #include "../API.au3"
3 |
4 | ; Set basic app info
5 | _API_MGR_SetName("My APP adapter")
6 | _API_MGR_SetVer("1.0 BETA")
7 | _API_MGR_SetDescription("This adapter wraps some stuff from my app")
8 |
9 | ; Init the _API manager
10 | _API_MGR_Init(4545)
11 | If @error Then
12 | MsgBox(64,"", "Failed to init API. Error " & @error)
13 | Exit
14 | EndIf
15 |
16 | ; Register routes (Must be done after MGR_INIT)
17 | _API_MGR_ROUTER_GET('/my-first-route', _CB_MyFirstRoute)
18 | _API_MGR_ROUTER_GET('/my-second-route', _CB_MySecondRoute)
19 |
20 | ; Success
21 | ConsoleWrite("Please visit http://localhost:4545" & @LF)
22 |
23 | ; Handle requests
24 | While _API_MGR_ROUTER_HANDLE()
25 | WEnd
26 |
27 | ; Define your routes here
28 |
29 | Func _CB_MyFirstRoute()
30 | ; This UDF relies on the Dictionary object to create JSON (See more here: https://docs.microsoft.com/en-us/office/vba/language/reference/user-interface-help/dictionary-object)
31 |
32 | ; Create an empty object
33 | Local $object = ObjCreate("Scripting.Dictionary")
34 |
35 | ; Assign some values
36 |
37 | $object.add('username', @UserName)
38 | $object.add('computerName', @ComputerName)
39 |
40 | ; Pass the object back to our router, which will convert it into escaped json
41 | Return $object
42 | EndFunc
43 |
44 | Func _CB_MySecondRoute(Const $oRequest)
45 | ; the $oRequest passed to this function is an "Scripting.Dictionary", the same type of object we used to return data
46 |
47 | ; Create an empty object
48 | Local $object = ObjCreate("Scripting.Dictionary")
49 |
50 | ; Assign some values
51 | Local Const $queryParam1 = $oRequest.exists('param1') ? $oRequest.item('param1') : 'param1 not set. append ?param1= to the url see this value change'
52 |
53 | $object.add('param1', $queryParam1)
54 |
55 | ; Pass the object back to our router, which will convert it into escaped json
56 | Return $object
57 | EndFunc
58 |
59 |
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 | AutoIt-WS-API refdocs
--------------------------------------------------------------------------------
/Testing/Tests/TestApp.au3:
--------------------------------------------------------------------------------
1 | #include "../../API.AU3"
2 |
3 |
4 | ; Init the _API manager
5 | _API_MGR_Init(4545)
6 | If @error Then Exit(1)
7 | _API_MGR_ROUTER_GET('/empty-string-response', CB_EmptyStringResponse)
8 | _API_MGR_ROUTER_GET('/empty-array-response', CB_EmptyArrayResponse)
9 | _API_MGR_ROUTER_GET('/empty-object-response', CB_EmptyObjectResponse)
10 | _API_MGR_ROUTER_GET('/array-of-objects-response', CB_ArrayOfObjectsResponse)
11 | _API_MGR_ROUTER_GET('/object-of-arrays-response', CB_ObjectOfArrayResponse)
12 | _API_MGR_ROUTER_GET('/object-of-types-response', CB_ObjectOfTypesResponse)
13 |
14 |
15 | ; Handle requests
16 | While _API_MGR_ROUTER_HANDLE()
17 | WEnd
18 |
19 |
20 | Func CB_EmptyStringResponse()
21 | Return ''
22 | EndFunc
23 |
24 | Func CB_EmptyArrayResponse()
25 | Local const $arr[0] = []
26 | Return $arr
27 | EndFunc
28 |
29 | Func CB_EmptyObjectResponse()
30 | return ObjCreate("Scripting.Dictionary")
31 | EndFunc
32 |
33 | Func CB_ArrayOfObjectsResponse()
34 | Local Const $obj1 = ObjCreate("Scripting.Dictionary")
35 | $obj1.add('name', 'test')
36 | $obj1.add('number',1337)
37 | Local Const $obj2 = ObjCreate("Scripting.Dictionary")
38 | $obj2.add('name', 'test')
39 | $obj2.add('number', 22)
40 |
41 | Local Const $arr = [$obj1, $obj2]
42 |
43 | Return $arr
44 | EndFunc
45 |
46 | Func CB_ObjectOfArrayResponse()
47 | Local Const $arr = [1, 2, 3, 4, 5]
48 | Local Const $arr2 = [ObjCreate("Scripting.Dictionary")]
49 | Local Const $oObj = ObjCreate("Scripting.Dictionary")
50 | $oObj.add('arr', $arr)
51 | $oObj.add('arr2', $arr2)
52 | Return $oObj
53 | EndFunc
54 |
55 | Func CB_ObjectOfTypesResponse()
56 | Local Const $oObj = ObjCreate("Scripting.Dictionary")
57 | Local Const $arr[0] = []
58 | $oObj.add('string', '')
59 | $oObj.add('ip', '192.168.1.0')
60 | $oObj.add('number_a', 1337)
61 | $oObj.add('number_b', 13.37)
62 | $oObj.add('number_c', "13.37")
63 | $oObj.add('object', ObjCreate("Scripting.Dictionary"))
64 | $oObj.add('array', $arr)
65 | $oObj.add('null', Null)
66 | $oObj.add('bool_a', True)
67 | $oObj.add('bool_b', False)
68 | Return $oObj
69 | EndFunc
70 |
--------------------------------------------------------------------------------
/Examples/5) Get route header data.au3:
--------------------------------------------------------------------------------
1 | ; Include the UDF
2 | #include "../API.au3"
3 |
4 | ; Set basic app info
5 | _API_MGR_SetName("My APP adapter")
6 | _API_MGR_SetVer("1.0 BETA")
7 | _API_MGR_SetDescription("This adapter wraps some stuff from my app")
8 |
9 | ; Init the _API manager
10 | _API_MGR_Init(4545)
11 | If @error Then
12 | MsgBox(64,"", "Failed to init API. Error " & @error)
13 | Exit
14 | EndIf
15 |
16 | ; Register routes (Must be done after MGR_INIT)
17 | _API_MGR_ROUTER_GET('/my-first-route', _CB_MyFirstRoute)
18 | _API_MGR_ROUTER_GET('/my-second-route', _CB_MySecondRoute)
19 | _API_MGR_ROUTER_GET('/my-third-route', _CB_MyThirdRoute)
20 |
21 | ; Success
22 | ConsoleWrite("Please visit http://localhost:4545" & @LF)
23 |
24 | ; Handle requests
25 | While _API_MGR_ROUTER_HANDLE()
26 | WEnd
27 |
28 | ; Define your routes here
29 |
30 | Func _CB_MyFirstRoute()
31 | ; This UDF relies on the Dictionary object to create JSON (See more here: https://docs.microsoft.com/en-us/office/vba/language/reference/user-interface-help/dictionary-object)
32 |
33 | ; Create an empty object
34 | Local $object = ObjCreate("Scripting.Dictionary")
35 |
36 | ; Assign some values
37 |
38 | $object.add('username', @UserName)
39 | $object.add('computerName', @ComputerName)
40 |
41 | ; Pass the object back to our router, which will convert it into escaped json
42 | Return $object
43 | EndFunc
44 |
45 | Func _CB_MySecondRoute(Const $oRequest)
46 | ; the $oRequest passed to this function is an "Scripting.Dictionary", the same type of object we used to return data
47 |
48 | ; Create an empty object
49 | Local $object = ObjCreate("Scripting.Dictionary")
50 |
51 | ; Assign some values
52 | Local Const $queryParam1 = $oRequest.exists('param1') ? $oRequest.item('param1') : 'param1 not set. append ?param1= to the url see this value change'
53 |
54 | $object.add('param1', $queryParam1)
55 |
56 | ; Pass the object back to our router, which will convert it into escaped json
57 | Return $object
58 | EndFunc
59 |
60 | Func _CB_MyThirdRoute(Const $oRequest, Const $oHeaders)
61 | ;
62 | ; Create an empty object
63 | Local $object = ObjCreate("Scripting.Dictionary")
64 |
65 | ; List all headers
66 | Local $aHeaderKeys = $oHeaders.keys()
67 | For $i = 0 To $oHeaders.count() -1
68 | ; Fetch the header KEY
69 | Local $key = $aHeaderKeys[$i]
70 | Local $value = $oHeaders.item($key)
71 |
72 | ; Place in new SD
73 | $object.add($key, $value)
74 | Next
75 |
76 | ; Pass the object back to our router, which will convert it into escaped json
77 | Return $object
78 | EndFunc
79 |
80 |
--------------------------------------------------------------------------------
/generateDocs.au3:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | Global Const $source = InputBox("Source AU3 file", "", "API.au3")
4 | Global Const $targetHtml = InputBox("Source AU3 file", "", "Docs\index.html")
5 |
6 |
7 | Global Const $content = FileRead($source)
8 | Global Const $AutoItDoctemplate = 'Function %name% %name% %description%
Return Value Remarks %remarks%
Related %related%
'
9 | Global Const $RefIndex = 'AutoIt-WS-API refdocs '
10 |
11 | Global $aFuncDefs = getFncs()
12 | Global $aNames = getHeaderByName("Name")
13 | Global $aDescriptions = getHeaderByName("Description")
14 | Global $aRemarks = getHeaderByName("Remarks")
15 | Global $aRelateds = getHeaderByName("Related")
16 | Global $aReturns = getHeaderByName("Return values")
17 |
18 |
19 | For $i = 0 To UBound($aNames) - 1
20 | Global $calling = $aFuncDefs[$i]
21 | Global $name = StringStripWS($aNames[$i], 7)
22 | Global $description = $aDescriptions[$i]
23 | Global $remark = $aRemarks[$i]
24 | Global $related = $aRelateds[$i]
25 | Global $returns = $aReturns[$i]
26 |
27 | buildDoc($name, $calling, $description, $remark, $related, $returns)
28 | Next
29 | buildIndex()
30 |
31 |
32 | Func getHeaderByName($name)
33 | Return StringRegExp($content, "(?m)^;\h" & $name & "\h[.]{0,15}:\h*(.*)", 3)
34 | EndFunc
35 |
36 | Func getFncs()
37 | Return StringRegExp($content, '(?mi)^Func\h([_]{1}[a-z]+.*\)+)', 3)
38 | EndFunc
39 |
40 | Func buildIndex()
41 | _ArraySort($aNames)
42 | Local $sList = ""
43 | For $i = 1 To UBound($aNames) -1
44 | Local $name = $aNames[$i]
45 | $sList &= '' & $name & ' '
46 | Next
47 |
48 | Local $finalIndex = StringReplace($RefIndex, '%list%', $sList)
49 | Local $fh = FileOpen($targetHtml, 2)
50 | FileWrite($fh, $finalIndex)
51 | FileClose($fh)
52 |
53 | EndFunc
54 |
55 | Func buildDoc($name, $calling, $description, $remark, $related, $returns)
56 | Local $fHandle = FileOpen("Docs\refs\" & $name & ".html", 2)
57 | Local $template = $AutoItDoctemplate
58 | $template = StringReplace($template, '%name%', $name)
59 | $template = StringReplace($template, '%description%', $description)
60 | $template = StringReplace($template, '%remarks%', $remark)
61 | $template = StringReplace($template, '%calling%', $calling)
62 | $template = StringReplace($template, '%return%', $returns)
63 | $template = StringReplace($template, '%related%', getDocRelated($related))
64 | FileWrite($fHandle, $template)
65 | FileClose($fHandle)
66 | EndFunc
67 |
68 | Func getDocRelated($related)
69 | $related = StringStripWS($related, 8)
70 | Local $aRelated = StringSplit($related, ',')
71 | Local $sRelatedHrefs = ""
72 |
73 | For $i = 1 To $aRelated[0]
74 | $sRelatedHrefs &= StringFormat('%s , ', $aRelated[$i], $aRelated[$i])
75 | Next
76 |
77 | $sRelatedHrefs = StringTrimRight($sRelatedHrefs, 2)
78 |
79 | Return $sRelatedHrefs
80 |
81 | EndFunc
82 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## About AutoIt-API-WS
2 | **AutoIt-API-WS** is a light weight web server with expressive syntax, with the sole purpose of wrapping your existing AutoIt app with little to no effort.
3 |
4 | With **AutoIt-API-WS** you can send and receive data between any application or framework, as long they can handle HTTP requests, which is an industry standard today.
5 |
6 | Like my other communcations UDF [AutoIt-Socket-IO](https://www.autoitscript.com/forum/topic/188991-autoit-socket-io-networking-in-autoit-made-simple) **AutoIt-API-WS** is heavily inspired from the big boys, but this time its [Laravel](https://laravel.com/) and [Ruby on Rails](https://rubyonrails.org/).
7 |
8 | ## ~~Features~~ Highlights
9 | * No external or internal dependencies required
10 | * RESTful mindset when designed
11 | * Expressive syntax
12 | * Small codebase
13 | * Heavy use of Michelsofts [Dictionary object](https://docs.microsoft.com/en-us/office/vba/language/reference/user-interface-help/dictionary-object)
14 |
15 | ## Limitations
16 | * Not complient with any RFC, so something important could be missing. Time will tell!
17 | * One persons slow loris attack will kill the process forever.
18 |
19 | ## Example of implemetnation (With screenshots)
20 | This is a basic cRud operation with the RESTful mindset in use.
21 | ```AutoIt
22 | #include "API.au3"
23 | #include
24 |
25 | _API_MGR_SetName("My APP DB adapter")
26 | _API_MGR_SetVer("1.0 BETA")
27 | _API_MGR_SetDescription("This adapter allows you to get this n that")
28 |
29 | _API_MGR_Init(3000)
30 | _API_MGR_ROUTER_GET('/users', CB_GetUsers, 'string sortBy', 'Get all users, sortBy can be either asc or desc. asc is default')
31 | _API_MGR_ROUTER_GET('/users/{id}', CB_GetUsersById, 'int id*', 'Get user by id')
32 |
33 | While _API_MGR_ROUTER_HANDLE()
34 | WEnd
35 |
36 | Func DB_GetUsers()
37 | Local $userA = ObjCreate("Scripting.Dictionary")
38 | Local $userB = ObjCreate("Scripting.Dictionary")
39 |
40 | $userA.add('id', 1)
41 | $userA.add('name', 'TarreTarreTarre')
42 | $userA.add('age', 27)
43 |
44 | $userB.add('id', 2)
45 | $userB.add('name', @UserName)
46 | $userB.add('age', 22)
47 |
48 | Local $aRet = [$userA, $userB]
49 |
50 | Return $aRet
51 | EndFunc
52 |
53 | Func CB_GetUsers(Const $oRequest)
54 | Local $aUsers = DB_GetUsers()
55 |
56 | If $oRequest.exists('sortBy') Then
57 |
58 | Switch $oRequest.item('sortBy')
59 | Case Default
60 | Case 'asc'
61 |
62 | Case 'desc'
63 | _ArrayReverse($aUsers)
64 | EndSwitch
65 |
66 | EndIf
67 |
68 | Return $aUsers
69 |
70 | EndFunc
71 |
72 | Func CB_GetUsersById(Const $oRequest)
73 |
74 | Local Const $aUsers = DB_GetUsers()
75 | Local $foundUser = Null
76 |
77 | For $i = 0 To UBound($aUsers) -1
78 |
79 | Local $curUser = $aUsers[$i]
80 |
81 | If $curUser.item('id') == $oRequest.item('#id') Then
82 | $foundUser = $curUser
83 | ExitLoop
84 | EndIf
85 |
86 | Next
87 |
88 | If Not IsObj($foundUser) Then
89 | Return _API_RES_NotFound(StringFormat("Could not find user with ID %d", $oRequest.item('#id')))
90 | EndIf
91 |
92 | return $foundUser
93 |
94 | EndFunc
95 | ```
96 |
97 | When you visit [http://localhost:3000](http://localhost:3000) you are greeted with this pleasent view that will show you all your registred routes and some extra info you have provided.
98 |
99 | 
100 |
101 | When you visit [http://localhost:3000/users](http://localhost:3000/users) the UDF will return the array of objects as Json
102 |
103 | 
104 | And here is an example of [http://localhost:3000/users/1](http://localhost:3000/users/1)
105 |
106 | 
107 |
108 | If you want more examples, look in the **examples/**
--------------------------------------------------------------------------------
/Testing/TestSuite.au3:
--------------------------------------------------------------------------------
1 | #include-once
2 |
3 | ; #FUNCTION# ====================================================================================================================
4 | ; Name ..........: Runner
5 | ; Description ...:
6 | ; Syntax ........: Runner()
7 | ; Parameters ....:
8 | ; Return values .: None
9 | ; Author ........: Your Name
10 | ; Modified ......:
11 | ; Remarks .......:
12 | ; Related .......:
13 | ; Link ..........:
14 | ; Example .......: No
15 | ; ===============================================================================================================================
16 | Func Runner(Const ByRef $tests)
17 | Local Const $nMax = UBound($tests)
18 | Local $nSuccess = 0
19 | Local $nFailure = 0
20 |
21 | ConsoleWrite(@LF & @LF & "> # # # # Test start # # # # <" & @LF)
22 | For $i = 0 To $nMax - 1
23 | Local $curTest = $tests[$i]
24 | Local $funcName = FuncName($curTest)
25 |
26 | ;cw('-', StringFormat('Running test "%s"', $funcName))
27 | If Not $curTest() Then
28 | cw('!', StringFormat('[%d/%d]: %s (Failure!)', $i + 1, $nMax, $funcName))
29 | $nFailure += 1
30 | Else
31 | cw('+', StringFormat('[%d/%d]: %s (Success!)', $i + 1, $nMax, $funcName))
32 | $nSuccess += 1
33 | EndIf
34 | Next
35 |
36 | Local $iPercent = Round($nSuccess / $nMax * 100, 2)
37 |
38 | ConsoleWrite(@LF & "> # # # # Test results # # # # <" & @LF)
39 |
40 | If $iPercent < 100 Then
41 | cw('!', StringFormat("%s%% of tests succeded", $iPercent))
42 | Else
43 | cw('+', StringFormat("%s%% of tests succeded", $iPercent))
44 | EndIf
45 |
46 | ConsoleWrite("> # # # # Test results # # # # <" & @LF & @LF)
47 |
48 |
49 | EndFunc ;==>Runner
50 |
51 | ; #FUNCTION# ====================================================================================================================
52 | ; Name ..........: RunIsolatedInstanceOf
53 | ; Description ...: Run a script in an isolated instance
54 | ; Syntax ........: RunIsolatedInstanceOf($path)
55 | ; Parameters ....: $path - a pointer value.
56 | ; Return values .: None
57 | ; Author ........: TarreTarreTarre
58 | ; Modified ......:
59 | ; Remarks .......:
60 | ; Related .......:
61 | ; Link ..........:
62 | ; Example .......: No
63 | ; ===============================================================================================================================
64 | Func RunIsolatedInstanceOf($path)
65 | Return Run(StringFormat('"%s" "%s"', @AutoItExe, $path), @ScriptDir & "\Testing\Tests")
66 | EndFunc ;==>RunIsolatedInstanceOf
67 |
68 | ; #FUNCTION# ====================================================================================================================
69 | ; Name ..........: SyncRequest
70 | ; Description ...: Make a SYNc request
71 | ; Syntax ........: SyncRequest($method[, $uri = ""[, $payload = Null]])
72 | ; Parameters ....: $method - a map.
73 | ; $uri - [optional] an unknown value. Default is "".
74 | ; $payload - [optional] a pointer value. Default is Null.
75 | ; Return values .: None
76 | ; Author ........: TarreTarreTarre
77 | ; Modified ......:
78 | ; Remarks .......:
79 | ; Related .......:
80 | ; Link ..........:
81 | ; Example .......: No
82 | ; ===============================================================================================================================
83 | Func SyncRequest($method, $uri = "", $payload = Null)
84 | Local Const $oHTTP = ObjCreate("WinHttp.WinHttpRequest.5.1")
85 | $oHTTP.OPEN("GET", "http://localhost:4545" & $uri, False)
86 | $oHTTP.send()
87 | Return $oHTTP
88 | EndFunc ;==>SyncRequest
89 |
90 | ; #FUNCTION# ====================================================================================================================
91 | ; Name ..........: cw
92 | ; Description ...: consolewrite with some tabs and linefeeds
93 | ; Syntax ........: cw($color, $text)
94 | ; Parameters ....: $color - an unknown value.
95 | ; $text - a dll struct value.
96 | ; Return values .: None
97 | ; Author ........: TarreTarreTarre
98 | ; Modified ......:
99 | ; Remarks .......:
100 | ; Related .......:
101 | ; Link ..........:
102 | ; Example .......: No
103 | ; ===============================================================================================================================
104 | Func cw($color, $text)
105 | ConsoleWrite($color & @TAB & $text & @LF)
106 | EndFunc ;==>cw
107 |
--------------------------------------------------------------------------------
/docs/refs/style.css:
--------------------------------------------------------------------------------
1 | html{font-family:'Segoe UI','Lucida Grande',Verdana,Arial,Helvetica,sans-serif;font-size:.8125em}body{background-color:#fff;color:#000;font-weight:400}table{border-collapse:collapse;border-color:silver;border-style:solid;border-width:1px;margin-top:5px;width:100%}table.noborder{border-width:0}th{background-color:#ededed;border-color:silver;border-style:solid;border-width:1px;color:#707070;padding:4px;text-align:left}th.new{width:224px}th.old{width:226px}th.width25{width:25%}th.width75{width:75%}tr{padding:4px}tr.yellow,tr.yellowbold{background-color:#ffff9C}tr.yellowbold{font-weight:700}table td{border-color:silver;border-style:solid;border-width:1px;padding:4px}table.noborder td{border-width:0}td.center{text-align:center}td.right{text-align:right}td.sep{border-color:#fff silver}b{font-weight:700}u{text-decoration:underline}p{margin:0;padding-bottom:5px;padding-top:5px}p.center{text-align:center}span.underline{text-decoration:underline}.funcdesc{font-size:1.25em}ul.cell{margin:0 0 0 25px}div.indent{margin-left:32px}a,a:link{color:#00709f}a:visited{color:#03697a}a:active{color:#2a2a2a}a:hover{color:#3390b1}a,a:link,a:visited,a:active{text-decoration:none}a:hover{text-decoration:underline}a.ext:link,a.ext:visited,a.ext:active{text-decoration:underline}a.codeSnippetLink:hover{text-decoration:underline}h1{color:#707070;font-size:2.75em;font-weight:400;margin:0;padding-bottom:15px;padding-top:15px}.small{font-size:.875em;margin:-12px 0 -4px;padding-bottom:0;padding-top:9px}h2{color:#db7100;font-size:1.5em;font-weight:400;line-height:normal;margin:0;padding-bottom:5px;padding-top:25px}h3{color:navy;font-size:1.0625em;font-weight:700;line-height:normal;margin-bottom:0;margin-left:5px}pre,.code,.codeheader,.codebox{font-family:"Courier New",Courier,monospace}.code{white-space:nowrap}.codeheader{background-color:#ffa;border-bottom:1px solid #aaa;border-left:1px solid #aaa;border-right:1px solid #aaa;border-top:1px solid #aaa;padding:16px;white-space:normal}.codebox{border-bottom:1px solid #aaa;border-left:1px solid #aaa;border-right:1px solid #aaa;border-top:1px solid #aaa;color:#465584;overflow-x:auto;padding:8px 8px 16px;margin-top:5px;white-space:nowrap;width:99%}.S0{color:#2a2a2a}.S1{color:green;font-style:italic}.S2{color:green;font-style:italic}.S3{color:blue}.S4{color:#000090}.S5{color:blue}.S6{color:olive}.S7{color:red}.S8{color:#FF8000}.S9{color:#2a2a2a}.S10{color:gray}.S11{color:olive}.S12{color:#dc143c}.S13{background-color:#DDE8F0;color:red}.S14{color:#939}.S15{color:#0080ff}.bottom{padding-bottom:0;margin-bottom:0}.experimental{background-color:#ffffe0;border:solid;border-color:red;font-size:1.5em;font-weight:700;margin:12px;padding:4px}.specialnote{background-color:#fffffa;border:solid;border-color:blue;font-size:1.5em;font-weight:500;padding:4px}img.logo_v3{box-shadow:5px 5px 20px #aaa}.noPageBreak{page-break-inside:avoid}.codeSnippetContainer{min-width:260px;margin:0;padding:0}.codeSnippetContainerTabs{font-size:.8333em;height:20px;position:relative;vertical-align:middle;z-index:1}.codeSnippetContainerTab{border-bottom:2px solid #d0d2d2;border-top:1px solid #bbb;border-left:1px solid #929292;float:left;height:20px;padding:0 4px;width:auto;overflow:hidden;position:relative;font-weight:400}.codeSnippetContainerTabSingle{border:none;color:#00709f;vertical-align:baseline;top:10px;left:12px;position:relative;background-color:#fff}.codeSnippetContainerTabSingle a{color:#e66a38}.codeSnippetContainerTab a,.codeSnippetContainerTab a:link,.codeSnippetContainerTab a:visited,.codeSnippetContainerTab a:active{color:#1364c4;text-decoration:none}.codeSnippetContainerTab a:hover{color:#e66a38;position:relative}.codeSnippetContainerCodeContainer{border-bottom:3px solid #e5e5e5;border-left:3px solid #e5e5e5;border-right:3px solid #e5e5e5;clear:both;margin-bottom:0;position:relative;top:-3px}.codeSnippetToolBar{border-left:0 solid #e5e5e5;border-right:0 solid #e5e5e5;border-top:3px solid #e5e5e5;height:auto;width:auto}div.codeSnippetToolBarText{float:right;top:-12px;position:relative;background-color:#fff;width:auto;padding-left:4px;padding-right:4px;height:0;vertical-align:top}div.codeSnippetToolBarText>a:link,div.codeSnippetToolBarText>a:visited,div.codeSnippetToolBarText>a:active{margin-left:5px;margin-right:5px;text-decoration:none;background-color:#fff;padding-left:4px;padding-right:4px}div.codeSnippetToolBarText>a:hover{text-decoration:underline}.codeSnippetContainerCode{margin-top:14px;padding:5px 10px;width:auto}.codeSnippetContainerCode div{padding:0;margin:0}.codeSnippetContainerCode pre{padding-left:5px;margin:0;font-style:normal;font-weight:400;overflow:auto;word-wrap:normal}#hhctrl{vertical-align:middle}#hhctrl-bottom{vertical-align:bottom}.codeSnippetContainerTab object{cursor:pointer;text-decoration:underline}.valign-top{vertical-align:text-top}
2 |
--------------------------------------------------------------------------------
/Testing.au3:
--------------------------------------------------------------------------------
1 | #include "Testing\TestSuite.au3"
2 |
3 | Global Const $tests = [testMostBasic, testRequest_GET, testRequest_POST, testRequest_PUT, testRequest_PATCH, testRequest_DELETE, testRequest_OPTIONS, testRequest_HEAD, testCB_EmptyStringResponse, testCB_CB_EmptyArrayResponse, testCB_EmptyObjectResponse, testCB_ArrayOfObjectsResponse, testCB_ObjectOfArrayResponse, testCB_ObjectOfTypesResponse]
4 |
5 | Runner($tests)
6 |
7 | Func testMostBasic()
8 | Local Const $pid = RunIsolatedInstanceOf("Most basic.au3")
9 | Local Const $oHTTP = SyncRequest("GET", "")
10 | ProcessClose($pid)
11 | Return $oHTTP.Status = 200
12 | EndFunc ;==>testMostBasic
13 |
14 | Func testRequest_GET()
15 | Local Const $pid = RunIsolatedInstanceOf("Basic response types.au3")
16 | Local Const $oHTTP = SyncRequest("GET", "/test")
17 | ProcessClose($pid)
18 | Return $oHTTP.Status = 200 And $oHTTP.ResponseText == 'OK'
19 | EndFunc ;==>testRequest_GET
20 |
21 | Func testRequest_POST()
22 | Local Const $pid = RunIsolatedInstanceOf("Basic response types.au3")
23 | Local Const $oHTTP = SyncRequest("POST", "/test")
24 | ProcessClose($pid)
25 | Return $oHTTP.Status = 200 And $oHTTP.ResponseText == 'OK'
26 | EndFunc ;==>testRequest_POST
27 |
28 | Func testRequest_PUT()
29 | Local Const $pid = RunIsolatedInstanceOf("Basic response types.au3")
30 | Local Const $oHTTP = SyncRequest("PUT", "/test")
31 | ProcessClose($pid)
32 | Return $oHTTP.Status = 200 And $oHTTP.ResponseText == 'OK'
33 | EndFunc ;==>testRequest_PUT
34 |
35 | Func testRequest_PATCH()
36 | Local Const $pid = RunIsolatedInstanceOf("Basic response types.au3")
37 | Local Const $oHTTP = SyncRequest("PATCH", "/test")
38 | ProcessClose($pid)
39 | Return $oHTTP.Status = 200 And $oHTTP.ResponseText == 'OK'
40 | EndFunc ;==>testRequest_PATCH
41 |
42 | Func testRequest_DELETE()
43 | Local Const $pid = RunIsolatedInstanceOf("Basic response types.au3")
44 | Local Const $oHTTP = SyncRequest("DELETE", "/test")
45 | ProcessClose($pid)
46 | Return $oHTTP.Status = 200 And $oHTTP.ResponseText == 'OK'
47 | EndFunc ;==>testRequest_DELETE
48 |
49 | Func testRequest_OPTIONS()
50 | Local Const $pid = RunIsolatedInstanceOf("Basic response types.au3")
51 | Local Const $oHTTP = SyncRequest("OPTIONS", "/test")
52 | ProcessClose($pid)
53 | Return $oHTTP.Status = 200 And $oHTTP.ResponseText == 'OK'
54 | EndFunc ;==>testRequest_OPTIONS
55 |
56 | Func testRequest_HEAD()
57 | Local Const $pid = RunIsolatedInstanceOf("Basic response types.au3")
58 | Local Const $oHTTP = SyncRequest("HEAD", "/test")
59 | ProcessClose($pid)
60 | Return $oHTTP.Status = 200 And $oHTTP.ResponseText == 'OK'
61 | EndFunc ;==>testRequest_HEAD
62 |
63 | Func testCB_EmptyStringResponse()
64 | Local Const $pid = RunIsolatedInstanceOf("TestApp.au3")
65 | Local Const $oHTTP = SyncRequest("GET", "/empty-string-response")
66 | ProcessClose($pid)
67 | Return $oHTTP.Status = 200 And $oHTTP.ResponseText == ''
68 | EndFunc ;==>testCB_EmptyStringResponse
69 |
70 | Func testCB_CB_EmptyArrayResponse()
71 | Local Const $pid = RunIsolatedInstanceOf("TestApp.au3")
72 | Local Const $oHTTP = SyncRequest("GET", "/empty-array-response")
73 | ProcessClose($pid)
74 | Return $oHTTP.Status = 200 And $oHTTP.ResponseText == '[]'
75 | EndFunc ;==>testCB_CB_EmptyArrayResponse
76 |
77 | Func testCB_EmptyObjectResponse()
78 | Local Const $pid = RunIsolatedInstanceOf("TestApp.au3")
79 | Local Const $oHTTP = SyncRequest("GET", "/empty-object-response")
80 | ProcessClose($pid)
81 | Return $oHTTP.Status = 200 And $oHTTP.ResponseText == '{}'
82 | EndFunc ;==>testCB_EmptyObjectResponse
83 |
84 | Func testCB_ArrayOfObjectsResponse()
85 | Local Const $pid = RunIsolatedInstanceOf("TestApp.au3")
86 | Local Const $oHTTP = SyncRequest("GET", "/array-of-objects-response")
87 | ProcessClose($pid)
88 | Return $oHTTP.Status = 200 And $oHTTP.ResponseText == '[{"name": "test","number": 1337},{"name": "test","number": 22}]'
89 | EndFunc ;==>testCB_ArrayOfObjectsResponse
90 |
91 | Func testCB_ObjectOfArrayResponse()
92 | Local Const $pid = RunIsolatedInstanceOf("TestApp.au3")
93 | Local Const $oHTTP = SyncRequest("GET", "/object-of-arrays-response")
94 | ProcessClose($pid)
95 | Return $oHTTP.Status = 200 And $oHTTP.ResponseText == '{"arr": [1,2,3,4,5],"arr2": [{}]}'
96 | EndFunc ;==>testCB_ObjectOfArrayResponse
97 |
98 | Func testCB_ObjectOfTypesResponse()
99 | Local Const $pid = RunIsolatedInstanceOf("TestApp.au3")
100 | Local Const $oHTTP = SyncRequest("GET", "/object-of-types-response")
101 | ProcessClose($pid)
102 | Return $oHTTP.Status = 200 And $oHTTP.ResponseText == '{"string": "","ip": "192.168.1.0","number_a": 1337,"number_b": 13.37,"number_c": "13.37","object": {},"array": [],"null": null,"bool_a": true,"bool_b": false}'
103 | EndFunc ;==>testCB_ObjectOfTypesResponse
104 |
--------------------------------------------------------------------------------
/API.au3:
--------------------------------------------------------------------------------
1 | #cs
2 | Copyright (c) 2020 TarreTarreTarre
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy
5 | of this software and associated documentation files (the "Software"), to deal
6 | in the Software without restriction, including without limitation the rights
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the Software is
9 | furnished to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in all
12 | copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | SOFTWARE.
21 | #ce
22 | #AutoIt3Wrapper_Au3Check_Parameters=-q -d -w 1 -w 2 -w 3 -w- 4 -w 5 -w 6 -w 7
23 | #include-once
24 |
25 | #Region Respons statuses
26 | Global Const $API_STATUS_OK = "200 OK"
27 | Global Const $API_STATUS_CREATED = "201 CREATED"
28 | Global Const $API_STATUS_NO_CONTENT = "204 NO CONTENT"
29 | Global Const $API_STATUS_BAD_REQUEST = "400 BAD REQUEST"
30 | Global Const $API_STATUS_UNAUTHORIZED = "401 UNAUTHORIZED"
31 | Global Const $API_STATUS_FORBIDDEN = "403 FORBIDDEN"
32 | Global Const $API_STATUS_NOT_FOUND = "404 NOT FOUND"
33 | Global Const $API_STATUS_CONFLICT = "409 CONFLICT"
34 | Global Const $API_STATUS_INTERNAL_SERVER_ERROR = "500 INTERNAL SERVER ERROR"
35 | Global Const $API_STATUS_GATEWAY_TIMEOUT = "504 GATEWAY TIMEOUT"
36 | #EndRegion Respons statuses
37 |
38 | #Region Mimes (Content types)
39 | Global Const $API_CONTENT_TYPE_TEXTJSON = "text/json"
40 | Global Const $API_CONTENT_TYPE_TEXTHTML = "text/html"
41 | #EndRegion Mimes (Content types)
42 |
43 | #Region Internals
44 | Global $g__API_MainSocket = Null
45 | Global $g__API_Prefix = ''
46 | Global $g__API_StatusTextToUse = $API_STATUS_OK
47 | Global $g__API_CONTENT_TYPEToUse = $API_STATUS_OK
48 | Global $g__API_RegistredRoutes[1] = [0]
49 | Global $g__API_ApiName = "Untitled API"
50 | Global $g__API_ApiVer = "1.0.0"
51 | Global $g__API_ApiDescription = ""
52 | Global Const $g__API_sUDFVer = "1.0.0-beta"
53 | Global Const $g__API_DocTemplate = '{title} (V {ver}) {title} V {ver}
{description}
All requests must be x-www-form-urlencoded
'
54 | #EndRegion Internals
55 |
56 | ; #FUNCTION# ====================================================================================================================
57 | ; Name ..........: _API_GetUDFVer
58 | ; Description ...: Get the semantic version of the UDF
59 | ; Syntax ........: _API_GetUDFVer()
60 | ; Parameters ....: None
61 | ; Return values .: SEMVER string (X.Y.Z-)
62 | ; Author ........: TarreTarreTarre
63 | ; Modified ......:
64 | ; Remarks .......: See more on semver @ http://semver.org/
65 | ; Related .......:
66 | ; Link ..........: http://semver.org/
67 | ; Example .......: No
68 | ; ===============================================================================================================================
69 | Func _API_GetUDFVer()
70 | Return $g__API_sUDFVer
71 | EndFunc ;==>_API_GetUDFVer
72 |
73 | ; #FUNCTION# ====================================================================================================================
74 | ; Name ..........: _API_MGR_SetName
75 | ; Description ...: Set the name of your API (Not parsed, just for docs)
76 | ; Syntax ........: _API_MGR_SetName($sName)
77 | ; Parameters ....: $sName - a string value.
78 | ; Return values .: None
79 | ; Author ........: TarreTarreTarre
80 | ; Modified ......:
81 | ; Remarks .......:
82 | ; Related .......: _API_MGR_SetVer, _API_MGR_SetDescription
83 | ; Link ..........:
84 | ; Example .......: No
85 | ; ===============================================================================================================================
86 | Func _API_MGR_SetName($sName)
87 | $g__API_ApiName = $sName
88 | EndFunc ;==>_API_MGR_SetName
89 |
90 | ; #FUNCTION# ====================================================================================================================
91 | ; Name ..........: _API_MGR_SetVer
92 | ; Description ...: Set the version of your API (Not parsed, just for docs)
93 | ; Syntax ........: _API_MGR_SetVer($sVer)
94 | ; Parameters ....: $sVer - a string value.
95 | ; Return values .: None
96 | ; Author ........: TarreTarreTarre
97 | ; Modified ......:
98 | ; Remarks .......:
99 | ; Related .......: _API_MGR_SetName, _API_MGR_SetDescription
100 | ; Link ..........:
101 | ; Example .......: No
102 | ; ===============================================================================================================================
103 | Func _API_MGR_SetVer($sVer)
104 | $g__API_ApiVer = $sVer
105 | EndFunc ;==>_API_MGR_SetVer
106 |
107 | ; #FUNCTION# ====================================================================================================================
108 | ; Name ..........: _API_MGR_SetDescription
109 | ; Description ...: Set the description of your API (Not parsed, just for docs)
110 | ; Syntax ........: _API_MGR_SetDescription($sDesc)
111 | ; Parameters ....: $sDesc - a string value.
112 | ; Return values .: None
113 | ; Author ........: TarreTarreTarre
114 | ; Modified ......:
115 | ; Remarks .......:
116 | ; Related .......: _API_MGR_SetVer, _API_MGR_SetName
117 | ; Link ..........:
118 | ; Example .......: No
119 | ; ===============================================================================================================================
120 | Func _API_MGR_SetDescription($sDesc)
121 | $g__API_ApiDescription = $sDesc
122 | EndFunc ;==>_API_MGR_SetDescription
123 |
124 | ; #FUNCTION# ====================================================================================================================
125 | ; Name ..........: _API_MGR_Init
126 | ; Description ...: Initializes the API and starts listening on the given port. Default is 8080
127 | ; Syntax ........: _API_MGR_Init([$port = 3333[, $ipAdress = "127.0.0.1"]])
128 | ; Parameters ....: $port - [optional] a pointer value. Default is 8080
129 | ; $ipAdress - [optional] an integer value. Default is "127.0.0.1".
130 | ; Return values .: None
131 | ; Author ........: TarreTarreTarre
132 | ; Modified ......:
133 | ; Remarks .......:
134 | ; Related .......: _API_MGR_ROUTER_HANDLE
135 | ; Link ..........:
136 | ; Example .......: No
137 | ; ===============================================================================================================================
138 | Func _API_MGR_Init($port = 8080, $ipAdress = "127.0.0.1")
139 |
140 | ; Start TCP udf
141 | TCPStartup()
142 |
143 | ; Create main socket
144 | Local $mainSocket = TCPListen($ipAdress, $port)
145 |
146 | If @error Then
147 | Return SetError(1, 0, Null)
148 | Exit
149 | EndIf
150 |
151 | ; Set default socket (Only once)
152 | If Not $g__API_MainSocket Then
153 | $g__API_MainSocket = $mainSocket
154 | EndIf
155 |
156 | ; Register default routes
157 | _API_MGR_ROUTER_GET("/", __API_ListRegistredRoutes, "", "Documentation (This page)", $mainSocket)
158 |
159 | Return $mainSocket
160 |
161 | EndFunc ;==>_API_MGR_Init
162 |
163 | ; #FUNCTION# ====================================================================================================================
164 | ; Name ..........: _API_MGR_ROUTER_Prefix
165 | ; Description ...: Sets a given prefix to the following router registrations.
166 | ; Syntax ........: _API_MGR_ROUTER_Prefix($sPrefix)
167 | ; Parameters ....: $sPrefix - a string value.
168 | ; Return values .: None
169 | ; Author ........: TarreTarreTarre
170 | ; Modified ......:
171 | ; Remarks .......:
172 | ; Related .......: _API_MGR_ROUTER_EndPrefix, _API_MGR_ROUTER_HANDLE, _API_MGR_ROUTER_Register, _API_MGR_ROUTER_GET, _API_MGR_ROUTER_POST, _API_MGR_ROUTER_PUT, _API_MGR_ROUTER_PATCH, _API_MGR_ROUTER_DELETE
173 | ; Link ..........:
174 | ; Example .......: No
175 | ; ===============================================================================================================================
176 | Func _API_MGR_ROUTER_Prefix($sPrefix)
177 | $g__API_Prefix = $sPrefix
178 | EndFunc ;==>_API_MGR_ROUTER_Prefix
179 |
180 | ; #FUNCTION# ====================================================================================================================
181 | ; Name ..........: _API_MGR_ROUTER_EndPrefix
182 | ; Description ...: Removes the prefix for the following router registrations
183 | ; Syntax ........: _API_MGR_ROUTER_EndPrefix([$sDummy = ""])
184 | ; Parameters ....: $sDummy - [optional] a string value. Default is "".
185 | ; Return values .: None
186 | ; Author ........: TarreTarreTarre
187 | ; Modified ......:
188 | ; Remarks .......: $sDummy can be used to give a visual representation, it will not be parsed
189 | ; Related .......: _API_MGR_ROUTER_Prefix
190 | ; Link ..........:
191 | ; Example .......: No
192 | ; ===============================================================================================================================
193 | Func _API_MGR_ROUTER_EndPrefix($sDummy = "")
194 | #forceref $sDummy
195 | _API_MGR_ROUTER_Prefix("")
196 | EndFunc ;==>_API_MGR_ROUTER_EndPrefix
197 |
198 | ; #FUNCTION# ====================================================================================================================
199 | ; Name ..........: _API_MGR_ROUTER_Register
200 | ; Description ...: Register a HTTP route with a callback.
201 | ; Syntax ........: _API_MGR_ROUTER_Register($method, $route, $callBack[, $requiredParams = ""[, $description = "No description"[,
202 | ; $mainSocket = $g__API_MainSocket]]])
203 | ; Parameters ....: $method - a map.
204 | ; $route - an unknown value.
205 | ; $callBack - an unknown value.
206 | ; $requiredParams - [optional] an unknown value. Default is "".
207 | ; $description - [optional] a binary variant value. Default is "No description".
208 | ; $mainSocket - [optional] a map. Default is $g__API_MainSocket.
209 | ; Return values .: None
210 | ; Author ........: TarreTarreTarre
211 | ; Modified ......:
212 | ; Remarks .......: The $callback param CAN have 2, 1 or 0 (ZERO) params. Func MyCallback(Const $oRequest, Const, $oHeaders), Func MyCallback(Const $oRequest), Func MyCallback(). The $requiredParams has the following format "type Name<*required>" and is separated by pipelines, for example. "string name*" = "String $name (Required)", if <*> is not used, the result will be "String $name (Optional)"
213 | ; Related .......: _API_MGR_ROUTER_Prefix, _API_MGR_ROUTER_HANDLE, _API_MGR_ROUTER_GET, _API_MGR_ROUTER_POST, _API_MGR_ROUTER_PUT, _API_MGR_ROUTER_PATCH, _API_MGR_ROUTER_DELETE
214 | ; Link ..........:
215 | ; Example .......: No
216 | ; ===============================================================================================================================
217 | Func _API_MGR_ROUTER_Register($method, $route, $callBack, $requiredParams = "", $description = "No description", Const $mainSocket = $g__API_MainSocket)
218 | $route = $g__API_Prefix & $route
219 |
220 | ; Prepend slash if needed
221 | If StringLeft($route, 1) <> "/" Then
222 | $route = "/" & $route
223 | EndIf
224 |
225 | If Not StringRegExp($route, '^[a-z0-9_\/-\{\}]+') Then
226 | If Not @Compiled Then ConsoleWriteError(StringFormat('Failed to register: "%s" => "%s" (Regex mismatch)', $method, $route) & @LF)
227 | Return SetError(1, 0, Null)
228 | EndIf
229 |
230 | Local Const $fqrn = StringFormat("%s %s", $method, $route)
231 | Local Const $pairs[5] = [$fqrn, $callBack, StringSplit($requiredParams, "|"), $description, $mainSocket]
232 |
233 | ; Add to stack
234 | ReDim $g__API_RegistredRoutes[$g__API_RegistredRoutes[0] + 2]
235 | $g__API_RegistredRoutes[$g__API_RegistredRoutes[0] + 1] = $pairs
236 | $g__API_RegistredRoutes[0] += 1
237 |
238 | ; For debug only
239 | If Not @Compiled Then ConsoleWrite(StringFormat('Route registred: "%s" => "%s"', $fqrn, FuncName($callBack)) & @LF)
240 | EndFunc ;==>_API_MGR_ROUTER_Register
241 |
242 | ; #FUNCTION# ====================================================================================================================
243 | ; Name ..........: _API_MGR_ROUTER_ANY
244 | ; Description ...: Shorthand for _API_MGR_ROUTER_Register
245 | ; Syntax ........: _API_MGR_ROUTER_ANY($route, $callBack[, $requiredParams = ""[, $description = "No description"[,
246 | ; $mainSocket = $g__API_MainSocket]]])
247 | ; Parameters ....: $route - an unknown value.
248 | ; $callBack - an unknown value.
249 | ; $requiredParams - [optional] an unknown value. Default is "".
250 | ; $description - [optional] a binary variant value. Default is "No description".
251 | ; $mainSocket - [optional] a map. Default is $g__API_MainSocket.
252 | ; Return values .: None
253 | ; Author ........: TarreTarreTarre
254 | ; Modified ......:
255 | ; Remarks .......: This will register the most common route methods. Read more at _API_MGR_ROUTER_Register
256 | ; Related .......: _API_MGR_ROUTER_Register
257 | ; Link ..........:
258 | ; Example .......: No
259 | ; ===============================================================================================================================
260 | Func _API_MGR_ROUTER_ANY($route, $callBack, $requiredParams = "", $description = "No description", Const $mainSocket = $g__API_MainSocket)
261 | Local Const $CommonPaths = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS', 'HEAD']
262 | For $i = 0 To UBound($CommonPaths) -1
263 | Local $method = $CommonPaths[$i]
264 | _API_MGR_ROUTER_Register($method, $route, $callBack, $requiredParams, $description, $mainSocket)
265 | Next
266 | EndFunc
267 |
268 | ; #FUNCTION# ====================================================================================================================
269 | ; Name ..........: _API_MGR_ROUTER_GET
270 | ; Description ...: Shorthand for _API_MGR_ROUTER_Register
271 | ; Syntax ........: _API_MGR_ROUTER_GET($route, $callBack[, $requiredParams = ""[, $description = "No description"[,
272 | ; $mainSocket = $g__API_MainSocket]]])
273 | ; Parameters ....: $route - an unknown value.
274 | ; $callBack - an unknown value.
275 | ; $requiredParams - [optional] an unknown value. Default is "".
276 | ; $description - [optional] a binary variant value. Default is "No description".
277 | ; $mainSocket - [optional] a map. Default is $g__API_MainSocket.
278 | ; Return values .: None
279 | ; Author ........: TarreTarreTarre
280 | ; Modified ......:
281 | ; Remarks .......: Read more at _API_MGR_ROUTER_Register
282 | ; Related .......: _API_MGR_ROUTER_Register
283 | ; Link ..........:
284 | ; Example .......: No
285 | ; ===============================================================================================================================
286 | Func _API_MGR_ROUTER_GET($route, $callBack, $requiredParams = "", $description = "No description", Const $mainSocket = $g__API_MainSocket)
287 | Return _API_MGR_ROUTER_Register("GET", $route, $callBack, $requiredParams, $description, $mainSocket)
288 | EndFunc ;==>_API_MGR_ROUTER_GET
289 |
290 | ; #FUNCTION# ====================================================================================================================
291 | ; Name ..........: _API_MGR_ROUTER_POST
292 | ; Description ...: Shorthand for _API_MGR_ROUTER_Register
293 | ; Syntax ........: _API_MGR_ROUTER_POST($route, $callBack[, $requiredParams = ""[, $description = "No description"[,
294 | ; $mainSocket = $g__API_MainSocket]]])
295 | ; Parameters ....: $route - an unknown value.
296 | ; $callBack - an unknown value.
297 | ; $requiredParams - [optional] an unknown value. Default is "".
298 | ; $description - [optional] a binary variant value. Default is "No description".
299 | ; $mainSocket - [optional] a map. Default is $g__API_MainSocket.
300 | ; Return values .: None
301 | ; Author ........: TarreTarreTarre
302 | ; Modified ......:
303 | ; Remarks .......: Read more at _API_MGR_ROUTER_Register
304 | ; Related .......: _API_MGR_ROUTER_Register
305 | ; Link ..........:
306 | ; Example .......: No
307 | ; ===============================================================================================================================
308 | Func _API_MGR_ROUTER_POST($route, $callBack, $requiredParams = "", $description = "No description", Const $mainSocket = $g__API_MainSocket)
309 | Return _API_MGR_ROUTER_Register("POST", $route, $callBack, $requiredParams, $description, $mainSocket)
310 | EndFunc ;==>_API_MGR_ROUTER_POST
311 |
312 | ; #FUNCTION# ====================================================================================================================
313 | ; Name ..........: _API_MGR_ROUTER_PUT
314 | ; Description ...: Shorthand for _API_MGR_ROUTER_Register
315 | ; Syntax ........: _API_MGR_ROUTER_PUT($route, $callBack[, $requiredParams = ""[, $description = "No description"[,
316 | ; $mainSocket = $g__API_MainSocket]]])
317 | ; Parameters ....: $route - an unknown value.
318 | ; $callBack - an unknown value.
319 | ; $requiredParams - [optional] an unknown value. Default is "".
320 | ; $description - [optional] a binary variant value. Default is "No description".
321 | ; $mainSocket - [optional] a map. Default is $g__API_MainSocket.
322 | ; Return values .: None
323 | ; Author ........: TarreTarreTarre
324 | ; Modified ......:
325 | ; Remarks .......: Read more at _API_MGR_ROUTER_Register
326 | ; Related .......: _API_MGR_ROUTER_Register
327 | ; Link ..........:
328 | ; Example .......: No
329 | ; ===============================================================================================================================
330 | Func _API_MGR_ROUTER_PUT($route, $callBack, $requiredParams = "", $description = "No description", Const $mainSocket = $g__API_MainSocket)
331 | Return _API_MGR_ROUTER_Register("PUT", $route, $callBack, $requiredParams, $description, $mainSocket)
332 | EndFunc ;==>_API_MGR_ROUTER_PUT
333 |
334 | ; #FUNCTION# ====================================================================================================================
335 | ; Name ..........: _API_MGR_ROUTER_PATCH
336 | ; Description ...: Shorthand for _API_MGR_ROUTER_Register
337 | ; Syntax ........: _API_MGR_ROUTER_PATCH($route, $callBack[, $requiredParams = ""[, $description = "No description"[,
338 | ; $mainSocket = $g__API_MainSocket]]])
339 | ; Parameters ....: $route - an unknown value.
340 | ; $callBack - an unknown value.
341 | ; $requiredParams - [optional] an unknown value. Default is "".
342 | ; $description - [optional] a binary variant value. Default is "No description".
343 | ; $mainSocket - [optional] a map. Default is $g__API_MainSocket.
344 | ; Return values .: None
345 | ; Author ........: TarreTarreTarre
346 | ; Modified ......:
347 | ; Remarks .......: Read more at _API_MGR_ROUTER_Register
348 | ; Related .......: _API_MGR_ROUTER_Register
349 | ; Link ..........:
350 | ; Example .......: No
351 | ; ===============================================================================================================================
352 | Func _API_MGR_ROUTER_PATCH($route, $callBack, $requiredParams = "", $description = "No description", Const $mainSocket = $g__API_MainSocket)
353 | Return _API_MGR_ROUTER_Register("PATCH", $route, $callBack, $requiredParams, $description, $mainSocket)
354 | EndFunc ;==>_API_MGR_ROUTER_PATCH
355 |
356 | ; #FUNCTION# ====================================================================================================================
357 | ; Name ..........: _API_MGR_ROUTER_DELETE
358 | ; Description ...: Shorthand for _API_MGR_ROUTER_Register
359 | ; Syntax ........: _API_MGR_ROUTER_DELETE($route, $callBack[, $requiredParams = ""[, $description = "No description"[,
360 | ; $mainSocket = $g__API_MainSocket]]])
361 | ; Parameters ....: $route - an unknown value.
362 | ; $callBack - an unknown value.
363 | ; $requiredParams - [optional] an unknown value. Default is "".
364 | ; $description - [optional] a binary variant value. Default is "No description".
365 | ; $mainSocket - [optional] a map. Default is $g__API_MainSocket.
366 | ; Return values .: None
367 | ; Author ........: TarreTarreTarre
368 | ; Modified ......:
369 | ; Remarks .......: Read more at _API_MGR_ROUTER_Register
370 | ; Related .......: _API_MGR_ROUTER_Register
371 | ; Link ..........:
372 | ; Example .......: No
373 | ; ===============================================================================================================================
374 | Func _API_MGR_ROUTER_DELETE($route, $callBack, $requiredParams = "", $description = "No description", Const $mainSocket = $g__API_MainSocket)
375 | Return _API_MGR_ROUTER_Register("DELETE", $route, $callBack, $requiredParams, $description, $mainSocket)
376 | EndFunc ;==>_API_MGR_ROUTER_DELETE
377 |
378 | ; #FUNCTION# ====================================================================================================================
379 | ; Name ..........: _API_MGR_ROUTER_HANDLE
380 | ; Description ...: This function handles all incoming requests. This Should be used in your applications mainloop
381 | ; Syntax ........: _API_MGR_ROUTER_HANDLE([$mainSocket = $g__API_MainSocket])
382 | ; Parameters ....: $mainSocket - [optional] a map. Default is $g__API_MainSocket.
383 | ; Return values .: None
384 | ; Author ........: TarreTarreTarre
385 | ; Modified ......:
386 | ; Remarks .......: This should be called at least every 100 ms
387 | ; Related .......: _API_MGR_INIT
388 | ; Link ..........:
389 | ; Example .......: No
390 | ; ===============================================================================================================================
391 | Func _API_MGR_ROUTER_HANDLE(Const $mainSocket = $g__API_MainSocket)
392 |
393 | ; Wait for connection
394 | ;ConsoleWrite("Waiting for incomming connection" & @LF)
395 | Do
396 | Local $connectedSocket = TCPAccept($mainSocket)
397 | Until $connectedSocket <> -1
398 |
399 | If $connectedSocket < 0 Then Return ; // invalid
400 |
401 | ; Fetch request
402 | Local $response
403 |
404 | ;ConsoleWrite("Connection established. Waiting for request data" & @LF)
405 | Do
406 | Local $curResp = TCPRecv($connectedSocket, 1024)
407 | $response &= $curResp
408 | Until @error Or (StringLen($response) > 0 And $curResp == "")
409 |
410 | ; convert crlfs to lf
411 | $response = StringReplace($response, @CRLF, @LF)
412 |
413 | Local $responseContent = Null
414 | Local $routeFound = False
415 | Local $callbackFound = True
416 |
417 |
418 | For $i = 1 To $g__API_RegistredRoutes[0]
419 | Local $registredRoute = $g__API_RegistredRoutes[$i]
420 |
421 | ; Match TCP socket
422 | If $registredRoute[4] <> $mainSocket Then
423 | ContinueLoop
424 | EndIf
425 |
426 | Local $routeName = $registredRoute[0] ; GET /path/to/stuff
427 | Local $routeNameAsRe = "^" & StringRegExpReplace($routeName, "(?i)(\{[a-z_]+[a-z_0-9]*\})", "([^/]+)") & "\/*$"; the route name but as an regex
428 | Local $callBack = $registredRoute[1]; Can be String or FuncName
429 |
430 | ; Get the requested path with option éx "GET /path/to/stuff/1" without query params ?etc
431 | Local $requestedRouteName = StringRegExp($response, '^((?:GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD) [^? ]+)[? ]', 1)
432 | If Not @error Then
433 | ; URI decode the url
434 | $requestedRouteName = __API_URIDecode($requestedRouteName[0])
435 | ; convert to pattern
436 | EndIf
437 |
438 | ; Preflight requests will cause $requestedRouteName to return 0, so for the time beign, we just throw these requests away.
439 | If $requestedRouteName == 0 Then ContinueLoop
440 |
441 | ; If we matched the route
442 |
443 | Local $aRouteParams = StringRegExp($requestedRouteName, $routeNameAsRe, 2); Will always match if the route exists
444 | If Not @error Then
445 | Local $key, $value
446 |
447 | ; ###################
448 | ; # Build oReuqest
449 | ; ###
450 | Local $oRequest = ObjCreate("Scripting.Dictionary")
451 |
452 | ; Attempt to get route params (prepended with _route_)
453 | If UBound($aRouteParams) > 1 Then
454 | Local $aHeaderReNames = StringRegExp($routeName, "(?i)\{([a-z_]+[a-z_0-9]*)\}", 3)
455 |
456 | For $j = 0 To UBound($aHeaderReNames) -1
457 | $key = $aHeaderReNames[$j]
458 | $value = $aRouteParams[$j +1]
459 | $oRequest.add('#' & $key, $value)
460 |
461 | Next
462 | EndIf
463 |
464 | ; First we look at the query string to get our initial data
465 | __API_ParseQueryByRE($oRequest, $response, "\?([^ ]*) HTTP")
466 |
467 | ; Then we replace / fill the rest with x-www-form-urlencoded keys
468 | __API_ParseQueryByRE($oRequest, $response, "\n{2}([^\n]+)", True)
469 |
470 | ; ###################
471 | ; # Build oHeaders
472 | ; ###
473 |
474 | Local $oHeaders = ObjCreate("Scripting.Dictionary")
475 |
476 | ; fetch Key:value
477 | Local $aHeadersRe = StringRegExp($response, "(?mi)^([a-z0-9_-]+): ([^\n]+)", 3)
478 |
479 | ;ConsoleWrite($response)
480 |
481 | If Not @error Then
482 | For $j = 0 To UBound($aHeadersRe) - 1 Step +2
483 | $key = $aHeadersRe[$j]
484 | $value = $aHeadersRe[$j + 1]
485 |
486 | $oHeaders.add($key,StringTrimRight($value, 1))
487 | Next
488 | EndIf
489 |
490 | ;Invoke user defined callback, try three combinations
491 | $responseContent = Call($callBack, $oRequest, $oHeaders)
492 | If @error == 0xDEAD And @extended = 0xBEEF Then
493 | $responseContent = Call($callBack, $oRequest)
494 | If @error == 0xDEAD And @extended = 0xBEEF Then
495 | $responseContent = Call($callBack)
496 | ; Flag that no method exists
497 | $callbackFound = False
498 | EndIf
499 | EndIf
500 |
501 | ; Flag that we found the route
502 | $routeFound = True
503 |
504 | ; stop looking
505 | ExitLoop
506 | EndIf
507 | Next
508 | ;ConsoleWrite("Handling completed. Closing connection" & @LF)
509 |
510 | If Not $routeFound Then
511 | $responseContent = _API_RES_NotFound(StringFormat("The route '%s' was not found.", $requestedRouteName))
512 | ElseIf Not $callbackFound Then
513 | $responseContent = _API_RES_InternalServerError(StringFormat("The callback '%s' was not found.", $callBack))
514 | EndIf
515 |
516 | ; Create request
517 | Local Const $httpResponse = __API_RES($responseContent, $g__API_StatusTextToUse, $g__API_CONTENT_TYPEToUse)
518 |
519 | ; Reset status
520 | _API_RES_SET_STATUS($API_STATUS_OK)
521 | _API_RES_SET_CONTENT_TYPE($API_CONTENT_TYPE_TEXTJSON)
522 |
523 | TCPSend($connectedSocket, $httpResponse)
524 | TCPCloseSocket($connectedSocket)
525 |
526 | Return True
527 |
528 | EndFunc ;==>_API_MGR_ROUTER_HANDLE
529 |
530 | #Region Response functions
531 |
532 | ; #FUNCTION# ====================================================================================================================
533 | ; Name ..........: _API_RES_SET_STATUS
534 | ; Description ...: Set the response status code and text for your response. The default value after each request is $API_STATUS_OK
535 | ; Syntax ........: _API_RES_SET_STATUS($statusCodeText)
536 | ; Parameters ....: $statusCodeText - a string value.
537 | ; Return values .: None
538 | ; Author ........: TarreTarreTarre
539 | ; Modified ......:
540 | ; Remarks .......: The most common statuses are defined as constants, see more at #Region Respons statuses
541 | ; Related .......: _API_RES_SET_CONTENT_TYPE
542 | ; Link ..........:
543 | ; Example .......: No
544 | ; ===============================================================================================================================
545 | Func _API_RES_SET_STATUS($statusCodeText)
546 | $g__API_StatusTextToUse = $statusCodeText
547 | EndFunc ;==>_API_RES_SET_STATUS
548 |
549 | ; #FUNCTION# ====================================================================================================================
550 | ; Name ..........: _API_RES_SET_CONTENT_TYPE
551 | ; Description ...: Set the content type of your request. The default value after each request is $API_CONTENT_TYPE_TEXTJSON
552 | ; Syntax ........: _API_RES_SET_CONTENT_TYPE($mime)
553 | ; Parameters ....: $mime - a map.
554 | ; Return values .: None
555 | ; Author ........: TarreTarreTarre
556 | ; Modified ......:
557 | ; Remarks .......: The most common statuses are defined as constants, see more at #Region Mimes (Content types)
558 | ; Related .......: _API_RES_SET_STATUS
559 | ; Link ..........:
560 | ; Example .......: No
561 | ; ===============================================================================================================================
562 | Func _API_RES_SET_CONTENT_TYPE($mime)
563 | $g__API_CONTENT_TYPEToUse = $mime
564 | EndFunc ;==>_API_RES_SET_CONTENT_TYPE
565 |
566 | ; #FUNCTION# ====================================================================================================================
567 | ; Name ..........: _API_RES_BadRequest
568 | ; Description ...: Shorthend function for a "bad request" response
569 | ; Syntax ........: _API_RES_BadRequest([$message = "Bad request"[, $ResponseStatus = $API_STATUS_BAD_REQUEST]])
570 | ; Parameters ....: $message - [optional] a map. Default is "Bad request".
571 | ; $ResponseStatus - [optional] an unknown value. Default is $API_STATUS_BAD_REQUEST.
572 | ; Return values .: None
573 | ; Author ........: TarreTarreTarre
574 | ; Modified ......:
575 | ; Remarks .......: The json will always return with this structure: {"description": "Custom message descrpition"} with the given status code
576 | ; Related .......: _API_RES_NotFound, _API_RES_InternalServerError
577 | ; Link ..........:
578 | ; Example .......: No
579 | ; ===============================================================================================================================
580 | Func _API_RES_BadRequest($message = "Bad request", $ResponseStatus = $API_STATUS_BAD_REQUEST)
581 |
582 | Local Const $oRes = ObjCreate("Scripting.Dictionary")
583 | $oRes.add('description', $message)
584 | _API_RES_SET_STATUS($ResponseStatus)
585 | Return $oRes
586 | EndFunc ;==>_API_RES_BadRequest
587 |
588 | ; #FUNCTION# ====================================================================================================================
589 | ; Name ..........: _API_RES_NotFound
590 | ; Description ...: Shorthend for "API_RES_BadRequest" that only takes 1 params instead of two
591 | ; Syntax ........: _API_RES_NotFound([$message = "Not found"])
592 | ; Parameters ....: $message - [optional] a map. Default is "Not found".
593 | ; Return values .: None
594 | ; Author ........: TarreTarreTarre
595 | ; Modified ......:
596 | ; Remarks .......:
597 | ; Related .......: _API_RES_BadRequest, _API_RES_InternalServerError
598 | ; Link ..........:
599 | ; Example .......: No
600 | ; ===============================================================================================================================
601 | Func _API_RES_NotFound($message = "Not found")
602 | Return _API_RES_BadRequest($message, $API_STATUS_NOT_FOUND)
603 | EndFunc ;==>_API_RES_NotFound
604 |
605 | ; #FUNCTION# ====================================================================================================================
606 | ; Name ..........: _API_RES_InternalServerError
607 | ; Description ...: Shorthend for "API_RES_BadRequest" that only takes 1 params instead of two
608 | ; Syntax ........: _API_RES_InternalServerError([$message = "Something went wrong in the server"])
609 | ; Parameters ....: $message - [optional] a map. Default is "Something went wrong in the server".
610 | ; Return values .: None
611 | ; Author ........: TarreTarreTarre
612 | ; Modified ......:
613 | ; Remarks .......:
614 | ; Related .......: _API_RES_BadRequest, _API_RES_NotFound
615 | ; Link ..........:
616 | ; Example .......: No
617 | ; ===============================================================================================================================
618 | Func _API_RES_InternalServerError($message = "Something went wrong in the server")
619 | Return _API_RES_BadRequest($message, $API_STATUS_INTERNAL_SERVER_ERROR)
620 | EndFunc ;==>_API_RES_InternalServerError
621 |
622 | #EndRegion Response functions
623 |
624 | #Region Internals
625 | Func __API_RES($content, $statusCodeText, $ContentType)
626 |
627 | ; Cast objects and arrays to json
628 | If IsObj($content) Or IsArray($content) Then
629 | $content = __API_RES_toJson($content)
630 | EndIf
631 |
632 | ; Return response data
633 | Return "HTTP/1.1 " & $statusCodeText & @LF & _
634 | "Access-Control-Allow-Origin: *" & @LF & _
635 | "Server: " & $g__API_ApiName & " V " & $g__API_ApiVer & " (AutoIt V" & @AutoItVersion & ")" & @LF & _
636 | "Content-Length: " & StringLen($content) & @LF & _
637 | "Content-Type: " & $ContentType & "; charset=utf-8" & @LF & @LF & _
638 | $content & @LF
639 | EndFunc ;==>__API_RES
640 |
641 | Func __API_RES_toJson(Const $content)
642 | Local $sRet = '', $key, $value
643 |
644 | ; Handle scripting dictionaries
645 | If IsObj($content) Then
646 |
647 | Local Const $aKeys = $content.keys()
648 | $sRet = "{"
649 |
650 | For $i = 0 To UBound($aKeys) - 1
651 | $key = $aKeys[$i]
652 | $value = $content.item($key)
653 | Local $passValueAsRawCusArray = False
654 |
655 | If IsArray($value) Or IsObj($value) Then
656 | $value = __API_RES_toJson($value)
657 | $passValueAsRawCusArray = True
658 | EndIf
659 |
660 | $sRet &= __API_RES_toJson_CreatePair($key, $value, $passValueAsRawCusArray) & ","
661 |
662 | Next
663 |
664 | $sRet = StringRight($sRet, 1) == ',' ? StringTrimRight($sRet, 1) & "}" : $sRet & "}"
665 |
666 | ElseIf IsArray($content) Then
667 | $sRet = '['
668 |
669 | For $key = 0 To UBound($content) - 1
670 | $value = $content[$key]
671 |
672 | ; see if we should nest
673 | If IsArray($value) Or IsObj($value) Then
674 | $value = __API_RES_toJson($value)
675 | Else
676 | $value = __API_RES_toJson_parseValue($value)
677 | EndIf
678 |
679 | $sRet &= $value & ","
680 |
681 | Next
682 |
683 | $sRet = StringRight($sRet, 1) == ',' ? StringTrimRight($sRet, 1) & "]" : $sRet & "]"
684 |
685 | EndIf
686 |
687 | Return $sRet
688 |
689 | EndFunc ;==>__API_RES_toJson
690 |
691 | Func __API_RES_toJson_CreatePair($key, $value, $passValueAsRawCusArray = False)
692 | Return StringFormat('"%s": %s', $key, __API_RES_toJson_parseValue($value, $passValueAsRawCusArray))
693 | EndFunc ;==>__API_RES_toJson_CreatePair
694 |
695 | Func __API_RES_toJson_parseValue($value, $bRaw = False)
696 |
697 | ; Return specials "as is"
698 | If $value == Null Then
699 | Return 'null'
700 | EndIf
701 |
702 | ; bools
703 | If IsBool($value) Then
704 | Return $value ? 'true' : 'false'
705 | EndIf
706 |
707 | ; binaries
708 | If IsBinary($value) Then
709 | Return String($value)
710 | EndIf
711 |
712 | ; Escape stringerals
713 | If IsString($value) And Not $bRaw Then
714 | ; Escape unicode
715 | $value = __API_URIEscapeUnicode($value)
716 | ; Escape slashes (This will ignore the unicode esapce)
717 | $value = StringRegExpReplace($value, "[\\](?!u\d{1})", "\\\\")
718 | ; Escape quotes
719 | $value = '"' & StringReplace($value, '"', '\"') & '"'
720 | EndIf
721 |
722 | ; consider empty strings as nulls
723 | If StringLen($value) == 0 Then
724 | $value = '""'
725 | EndIf
726 |
727 |
728 | Return $value
729 | EndFunc ;==>__API_RES_toJson_parseValue
730 |
731 | Func __API_ListRegistredRoutes()
732 | Local $response
733 |
734 | Local Const $template = $g__API_DocTemplate
735 |
736 | Local Const $routes = $g__API_RegistredRoutes
737 |
738 | Local $listGroupItems = ""
739 |
740 | For $i = 1 To $routes[0]
741 | Local $registredRoute = $routes[$i]
742 | Local $uri = $registredRoute[0]
743 | ;Local $callBack = $registredRoute[1]
744 | Local $aRequiredParams = $registredRoute[2]
745 | Local $description = $registredRoute[3]
746 |
747 | Local $sParams = ""
748 |
749 | If $aRequiredParams[0] > 0 And $aRequiredParams[1] <> '' Then
750 | For $j = 1 To $aRequiredParams[0]
751 | Local $param = $aRequiredParams[$j]
752 | Local $paramRequired = StringRight($param, 1) == "*"
753 | Local $displayName
754 |
755 | If $paramRequired Then
756 | $displayName = StringTrimRight($param, 1) & " (Required)"
757 | Else
758 | $displayName = $param & " (Optional)"
759 | EndIf
760 | $sParams &= StringFormat('%s', $displayName)
761 | Next
762 | EndIf
763 |
764 | Local $listGroupItem = '' & @LF & _
765 | '
' & @LF & _
766 | '
' & $uri & ' ' & @LF & _
767 | '' & @LF & _
768 | '
' & @LF & _
769 | $description & @LF & _
770 | '
' & @LF & _
771 | '
' & @LF & _
772 | ' Params ' & @LF & _
773 | $sParams & @LF & _
774 | ' ' & @LF & _
775 | '
'
776 |
777 | $listGroupItems &= $listGroupItem
778 | Next
779 |
780 | ; Use template
781 | $response = StringReplace($template, "{listGroupItems}", $listGroupItems)
782 | $response = StringReplace($response, "{title}", $g__API_ApiName)
783 | $response = StringReplace($response, "{description}", $g__API_ApiDescription)
784 | $response = StringReplace($response, "{ver}", $g__API_ApiVer)
785 |
786 | ; Set mime and status
787 | _API_RES_SET_CONTENT_TYPE($API_CONTENT_TYPE_TEXTHTML)
788 | _API_RES_SET_STATUS($API_STATUS_OK)
789 | ; Return response
790 | Return $response
791 | EndFunc ;==>__API_ListRegistredRoutes
792 |
793 | Func __API_ParseQueryByRE(Const ByRef $oRequest, Const ByRef $response, Const $RE, Const $bReplace = False)
794 | Local $aQueryParamstr = StringRegExp($response, $RE, 1)
795 |
796 | If Not @error Then
797 | $aQueryParamstr = StringSplit(__API_URIDecode($aQueryParamstr[0]), "&")
798 |
799 | ; add to request
800 | For $j = 1 To $aQueryParamstr[0]
801 | Local $pair = StringSplit($aQueryParamstr[$j], "=")
802 | If $pair[0] < 2 Then ContinueLoop; The queryString is broken and can be ignored
803 | Local $key = $pair[1]
804 | Local $value = $pair[2]
805 |
806 | If $bReplace And $oRequest.exists($key) Then $oRequest.remove($key)
807 |
808 | $oRequest.add($key, $value)
809 | Next
810 | EndIf
811 | EndFunc ;==>__API_ParseQueryByRE
812 |
813 | Func __API_URIDecode($sData)
814 | ; Prog@ndy
815 | Local $aData = StringSplit(StringReplace($sData, "+", " ", 0, 1), "%")
816 | $sData = ""
817 | For $i = 2 To $aData[0]
818 | $aData[1] &= Chr(Dec(StringLeft($aData[$i], 2))) & StringTrimLeft($aData[$i], 2)
819 | Next
820 |
821 | Return BinaryToString(StringToBinary($aData[1], 1), 4)
822 | EndFunc ;==>__API_URIDecode
823 |
824 | Func __API_URIEscapeUnicode($sInput)
825 | ; Malkey
826 | Local Const $sRet = Execute(StringRegExpReplace($sInput, '(.)', '(AscW("$1")>127?"\\u"&StringLower(Hex(AscW("$1"),4)):"$1")&') & "''")
827 | If Not $sRet Then Return $sInput
828 | Return $sRet
829 | EndFunc ;==>__API_URIEscapeUnicode
830 |
831 | #EndRegion Internals
832 |
--------------------------------------------------------------------------------