1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
|
.TH GOLF 2gg $VERSION $DATE Development Tools
.SH NAME
request \- Golf documentation (requests)
.SH DESCRIPTION
Golf applications run by processing requests. A request always takes form of an HTTP request, meaning a URL, an optional HTTP request body, and any environment variables. This is regardless of whether it's a \fBservice\fP or a \fBcommand-line\fP program.
.LP
.B REQUEST URL
.LP
A "request URL" is a URL that an outside caller (such as a web browser) uses to execute your Golf code. Aside from the scheme, domain and port, it's made up of:
.RS 4
\[bu]
application path,
.RE
.RS 4
\[bu]
request path, and
.RE
.RS 4
\[bu]
URL parameters.
.RE
Here's a breakdown of URL structure:
.RS 4
.EX
<scheme>://<domain>[:<port>]<application path><request path><parameters>
.EE
.RE
For example, in the following URL:
.RS 4
.EX
https://your.website.com/my-app/my-request/par1=val1/par2=val2
.EE
.RE
"/my-app" is application path, "/my-request" is request path and "/par1=val1/par2=val2" are parameters "par1" and "par2" with values "val1" and "val2". Together, application path and request path are called URL path.
.LP
.B APPLICATION PATH
.LP
The leading part of URL's path is called "application path". By default, application path is the application name (see \fBmgrg\fP with "-i" option) preceded by forward slash ("/"); if it's "shopping", then the default application path is:
.RS 4
.EX
/shopping
.EE
.RE
Application name can contain alphanumerical characters and hyphens.
.B - Customizing application path
You can change the application path by specifying it with "--path" parameter in \fBgg\fP when building; each application must have its own unique path. Note that whatever it may be, the application name must always be its last path segment. For example, if your application name is "shopping", then the application path may be:
.RS 4
.EX
/api/v2/shopping
.EE
.RE
An example of specifying the custom application path:
.RS 4
.EX
gg -q --path="/api/v2/shopping"
.EE
.RE
.LP
.B REQUEST PATH
.LP
Request path follows the application path, for instance:
.RS 4
.EX
https://some.web.site/shopping/buy-item
.EE
.RE
In this case the application path is "/shopping" and the request path is "/buy-item". It means that file "buy-item.golf" handles request "/buy-item" by implementing a \fBbegin-handler\fP "/buy-item" in it. As another example, file "services/manage-home.golf" (meaning "manage-home.golf" file in subdirectory "services") handles request "/services/manage-home" etc.
The request path must match (fully or partially) the path of the file name that implements it, with source directory being the root ("/"). Here is an example of implementing a request "/buy-item" in file "buy-item.golf":
.RS 4
.EX
begin-handler /buy-item public
get-param some_param
@Bought item: <<print-out some_param>>
end-handler
.EE
.RE
As an example of a path hierarchy, such as for example a hierarchy of resources, methods etc, \fBbegin-handler\fP may be:
.RS 4
.EX
begin-handler /items/wine-collection/red-wine/buy-item public
...
end-handler
.EE
.RE
then the URL to call it would be:
.RS 4
.EX
https://some.web.site/shopping/items/wine-collection/red-wine/buy-item
.EE
.RE
and might be implemented in file "items/wine-collection/red-wine/buy-item.golf", meaning under subdirectory "items", then subdirectory "wine-collection", then subdirectory "red-wine", then file "buy-item.golf".
.B - File/path naming conventions
By default, a request handler would be implemented in a source file whose path matches the request path, either fully or partially.
The simplest example is that "/buy-item" request must be implemented in file "buy-item.golf".
As a more involved example, request handler for "/items/wine-collection/red-wine/buy-item" can be implemented in file "items.golf" or file "items/wine-collection.golf" or file "items/wine-collection/red-wine.golf" or file "items/wine-collection/red-wine/buy-item.golf".
Each of these source files can contain any number of matching requests. For instance, file "items.golf" can contain request handlers for both "/items/wine-collection/red-wine/buy-item" and "/items/beer-collection/ipa-beer/buy-item"; while file "items/wine-collection.golf" can contain request handlers for both "items/wine-collection/red-wine" and "items/wine-collection/white-wine".
By the same token, file "items/wine-collection/red-wine/buy-item.golf" can implement both "/items/wine-collection/red-wine/buy-item" and "/items/wine-collection/red-wine/buy-item/sale" requests, as both requests match the file path.
Note that if you use "--single-file" option in \fBgg\fP, then each source ".golf" file must contain only a single request, and its request path must match the file path fully. So in this case, request handler for "/items/wine-collection/red-wine/buy-item" must be in file "items/wine-collection/red-wine/buy-item.golf", and no other request can be implemented in it.
.LP
.B URL PARAMETERS
.LP
The actual input parameters follow after the request path, and can be specified in a number of ways. A parameter value is generally URL encoded in any case.
.B - Path segments
A common way is to specify name and value separated by an equal sign within a single path segment:
.RS 4
.EX
https://some.web.site/shopping/buy-item/sku=4811/price=600/
.EE
.RE
This way, you have a readable representation of parameter names and values, while still maintaining the hierarchical form which conveys how are the parameters structured.
Here, the required request path is "/buy-item" and there are two input parameters ("sku" and "price") with values of "4811" and "600" respectively.
.B - Query string
Parameters can be specified after a question mark in a "name=value" form. For example, the full URL (with the same parameter values as above) may be:
.RS 4
.EX
https://some.web.site/shopping/buy-item?sku=4811&price=600
.EE
.RE
.B - Mixed
You can specify a mix of the above ways to write parameters, for instance the above URL can be written as:
.RS 4
.EX
https://some.web.site/shopping/buy-item/sku=4811?price=600
.EE
.RE
.B - Parameters
A parameter name can be comprised of alphanumeric characters, hyphens and underscores, and it must start with an alphabet character. Any hyphens are converted to underscores for the purpose of obtaining parameter value, see \fBget-param\fP. Do not use double underscore ("__") in parameter names.
Structuring your parameters, i.e. the order in a query path or path segments, and which ones (if any) are in a query string, is determined by you. Regardless of your choices, the code that handles a request is the same. In the example used here, you can obtain the parameters in request handler source file "buy-item.golf":
.RS 4
.EX
begin-handler /buy-item public
get-param sku
get-param price
run-query @mydb = "update wine_items set price='%s' where sku='%s'" : price, sku no-loop
@OKAY
end-handler
.EE
.RE
For a hierarchical URL path, you would write the same:
.RS 4
.EX
begin-handler /items/wine-collection/red-wine/buy-item public
get-param sku
get-param price
run-query @mydb = "update wine_items set price='%s' where sku='%s'" : price, sku no-loop
end-handler
.EE
.RE
.LP
.B MAXIMUM LENGTH
.LP
Maximum length of a request URL is 2500 bytes.
.LP
.B HOW GOLF HANDLES REQUESTS
.LP
There are generally two kinds of requests, depending on their origin. If a request comes from outside the process that's serving it, then it's an "external" request (such as from a web browser, a web API client, from command line execution etc). Conversely, if a request comes from inside the process that's serving it, it's an "internal" request - meaning one request handler is calling another within one the process(es) serving an application. Internal requests are made using \fBcall-handler\fP statement.
An external request is handled by a first available process:
.RS 4
\[bu]
For a \fBcommand-line\fP program, there is only a single process, and it handles a single requests before it exits.
.RE
.RS 4
\[bu]
For a \fBservice\fP application, there can be any number of processes running. A process is chosen to service a request if it is currently not serving other requests; this way there are no processes waiting idle unnecessarily. Each process is identical and can serve any request, i.e. it has all request handlers available to it. Thus, when a process is chosen to serve a request, then this process will simply execute its begin-handler.
.RE
.B - Processing a request
To handle a request, a process first calls a Golf dispatcher, which is automatically generated. It uses a request name to call the appropriate request handler, as explained above.
You can implement two hooks into request handling: one that executes before each request (\fBbefore-handler\fP) and one that executes afterwards (\fBafter-handler\fP).
At the end of the request, all request memory and all file handles allocated by Golf will be freed, except for process-scoped memory (see \fBmemory-handling\fP).
.B - Performance
Golf uses a hash table to match a request with a handler function, as well to match parameters. Typically, it takes only a single lookup to find the handler function/parameters, regardless of the number of possible request names/parameters a process may serve (be it 10 or 10,000 different names). Golf pre-generates a hash table at compile time, so no run-time cycles are spent on creating it. Also, the hash table is created as a continuous block of memory in the program's data segment, which loads as a part of the program (as a single memory copy) and is very fast because accessing the data needs no pointer translations. As a result, Golf dispatcher is extremely fast.
.B - Unrecognized requests
If no request has been recognized (i.e. request name does not match any request-handling ".golf" source file), then
.RS 4
\[bu]
no request handler will execute,
.RE
.RS 4
\[bu]
\fBbefore-handler\fP and \fBafter-handler\fP will not execute either,
.RE
.RS 4
\[bu]
and a "Request not found" error will be reported via \fBreport-error\fP.
.RE
.SH SEE ALSO
Requests
\fBrequest\fP
See all
\fBdocumentation\fP
|