├── .gitignore ├── API.au3 ├── Examples ├── 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 ├── 6) Returning nested JSON.au3 ├── 7) Returning Text or Html instead of Json.au3 ├── 8) Return other status codes.au3 └── 9) Get route request param data.au3 ├── README.md ├── Testing.au3 ├── Testing ├── TestSuite.au3 └── Tests │ ├── Basic response types.au3 │ ├── Most basic.au3 │ ├── Request data.au3 │ ├── Route params.au3 │ └── TestApp.au3 ├── docs ├── index.html └── refs │ ├── _API_GetUDFVer.html │ ├── _API_MGR_Init.html │ ├── _API_MGR_ROUTER_ANY.html │ ├── _API_MGR_ROUTER_DELETE.html │ ├── _API_MGR_ROUTER_EndPrefix.html │ ├── _API_MGR_ROUTER_GET.html │ ├── _API_MGR_ROUTER_HANDLE.html │ ├── _API_MGR_ROUTER_PATCH.html │ ├── _API_MGR_ROUTER_POST.html │ ├── _API_MGR_ROUTER_PUT.html │ ├── _API_MGR_ROUTER_Prefix.html │ ├── _API_MGR_ROUTER_Register.html │ ├── _API_MGR_SetDescription.html │ ├── _API_MGR_SetName.html │ ├── _API_MGR_SetVer.html │ ├── _API_RES_BadRequest.html │ ├── _API_RES_INTERNAL_SERVER_ERROR.html │ ├── _API_RES_InternalServerError.html │ ├── _API_RES_NotFound.html │ ├── _API_RES_SET_CONTENT_TYPE.html │ ├── _API_RES_SET_STATUS.html │ └── style.css └── generateDocs.au3 /.gitignore: -------------------------------------------------------------------------------- 1 | BackUp/ 2 | *.exe 3 | test.au3 -------------------------------------------------------------------------------- /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

{listGroupItems}
' 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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 -------------------------------------------------------------------------------- /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 -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /Examples/6) Returning nested JSON.au3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarreislam/Autoit-API-WS/f00b4188d326412778d3a72a9d6dbab794dc1975/Examples/6) Returning nested JSON.au3 -------------------------------------------------------------------------------- /Examples/7) Returning Text or Html instead of Json.au3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarreislam/Autoit-API-WS/f00b4188d326412778d3a72a9d6dbab794dc1975/Examples/7) Returning Text or Html instead of Json.au3 -------------------------------------------------------------------------------- /Examples/8) Return other status codes.au3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarreislam/Autoit-API-WS/f00b4188d326412778d3a72a9d6dbab794dc1975/Examples/8) Return other status codes.au3 -------------------------------------------------------------------------------- /Examples/9) Get route request param data.au3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarreislam/Autoit-API-WS/f00b4188d326412778d3a72a9d6dbab794dc1975/Examples/9) Get route request param data.au3 -------------------------------------------------------------------------------- /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 | ![Doc preview](https://i.imgur.com/UiNKTxy.png "Doc preview") 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 | ![User preview](https://i.imgur.com/msNIGMa.png "User preview") 104 | And here is an example of [http://localhost:3000/users/1](http://localhost:3000/users/1) 105 | 106 | ![User specified](https://i.imgur.com/Q3C4J6N.png "User specified") 107 | 108 | If you want more examples, look in the **examples/** -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | AutoIt-WS-API refdocs
-------------------------------------------------------------------------------- /docs/refs/_API_GetUDFVer.html: -------------------------------------------------------------------------------- 1 | Function _API_GetUDFVer

_API_GetUDFVer

Get the semantic version of the UDF

_API_GetUDFVer()

Return Value

SEMVER string (X.Y.Z-)

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

_API_MGR_Init($port = 8080, $ipAdress = "127.0.0.1")

Return Value

None

Remarks

Related

_API_MGR_ROUTER_HANDLE

-------------------------------------------------------------------------------- /docs/refs/_API_MGR_ROUTER_ANY.html: -------------------------------------------------------------------------------- 1 | Function _API_MGR_ROUTER_ANY

_API_MGR_ROUTER_ANY

Shorthand for _API_MGR_ROUTER_Register

_API_MGR_ROUTER_ANY($route, $callBack, $requiredParams = "", $description = "No description", Const $mainSocket = $g__API_MainSocket)

Return Value

None

Remarks

This will register the most common route methods. 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

_API_MGR_ROUTER_DELETE($route, $callBack, $requiredParams = "", $description = "No description", Const $mainSocket = $g__API_MainSocket)

Return Value

None

Remarks

Read more at _API_MGR_ROUTER_Register

Related

_API_MGR_ROUTER_Register

-------------------------------------------------------------------------------- /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

_API_MGR_ROUTER_EndPrefix($sDummy = "")

Return Value

None

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_GET.html: -------------------------------------------------------------------------------- 1 | Function _API_MGR_ROUTER_GET

_API_MGR_ROUTER_GET

Shorthand for _API_MGR_ROUTER_Register

_API_MGR_ROUTER_GET($route, $callBack, $requiredParams = "", $description = "No description", Const $mainSocket = $g__API_MainSocket)

Return Value

None

Remarks

Read more at _API_MGR_ROUTER_Register

Related

_API_MGR_ROUTER_Register

-------------------------------------------------------------------------------- /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

_API_MGR_ROUTER_HANDLE(Const $mainSocket = $g__API_MainSocket)

Return Value

None

Remarks

This should be called at least every 100 ms

Related

_API_MGR_INIT

-------------------------------------------------------------------------------- /docs/refs/_API_MGR_ROUTER_PATCH.html: -------------------------------------------------------------------------------- 1 | Function _API_MGR_ROUTER_PATCH

_API_MGR_ROUTER_PATCH

Shorthand for _API_MGR_ROUTER_Register

_API_MGR_ROUTER_PATCH($route, $callBack, $requiredParams = "", $description = "No description", Const $mainSocket = $g__API_MainSocket)

Return Value

None

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

_API_MGR_ROUTER_POST($route, $callBack, $requiredParams = "", $description = "No description", Const $mainSocket = $g__API_MainSocket)

Return Value

None

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

_API_MGR_ROUTER_PUT($route, $callBack, $requiredParams = "", $description = "No description", Const $mainSocket = $g__API_MainSocket)

Return Value

None

Remarks

Read more at _API_MGR_ROUTER_Register

Related

_API_MGR_ROUTER_Register

-------------------------------------------------------------------------------- /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.

_API_MGR_ROUTER_Prefix($sPrefix)

Return Value

None

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

-------------------------------------------------------------------------------- /docs/refs/_API_MGR_ROUTER_Register.html: -------------------------------------------------------------------------------- 1 | Function _API_MGR_ROUTER_Register

_API_MGR_ROUTER_Register

Register a HTTP route with a callback.

_API_MGR_ROUTER_Register($method, $route, $callBack, $requiredParams = "", $description = "No description", Const $mainSocket = $g__API_MainSocket)

Return Value

None

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

-------------------------------------------------------------------------------- /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)

_API_MGR_SetDescription($sDesc)

Return Value

None

Remarks

Related

_API_MGR_SetVer, _API_MGR_SetName

-------------------------------------------------------------------------------- /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)

_API_MGR_SetName($sName)

Return Value

None

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)

_API_MGR_SetVer($sVer)

Return Value

None

Remarks

Related

_API_MGR_SetName, _API_MGR_SetDescription

-------------------------------------------------------------------------------- /docs/refs/_API_RES_BadRequest.html: -------------------------------------------------------------------------------- 1 | Function _API_RES_BadRequest

_API_RES_BadRequest

Shorthend function for a "bad request" response

_API_RES_BadRequest($message = "Bad request", $ResponseStatus = $API_STATUS_BAD_REQUEST)

Return Value

None

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_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

_API_RES_INTERNAL_SERVER_ERROR($message = "Something went wrong in the server")

Return Value

None

Remarks

Related

_API_RES_BadRequest, _API_RES_NotFound

-------------------------------------------------------------------------------- /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

_API_RES_InternalServerError($message = "Something went wrong in the server")

Return Value

None

Remarks

Related

_API_RES_BadRequest, _API_RES_NotFound

-------------------------------------------------------------------------------- /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

_API_RES_NotFound($message = "Not found")

Return Value

None

Remarks

Related

_API_RES_BadRequest, _API_RES_InternalServerError

-------------------------------------------------------------------------------- /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

_API_RES_SET_CONTENT_TYPE($mime)

Return Value

None

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

_API_RES_SET_STATUS($statusCodeText)

Return Value

None

Remarks

The most common statuses are defined as constants, see more at #Region Respons statuses

Related

_API_RES_SET_CONTENT_TYPE

-------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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%

%calling%

Return Value

%return%

Remarks

%remarks%

Related

%related%

' 9 | Global Const $RefIndex = 'AutoIt-WS-API refdocs
    %list%
' 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 | --------------------------------------------------------------------------------