The @web module contains functions for interfacing with the World Wide Web.

@web Functions

:req(url,data,headers,method) #

Make a web request.

Parameters

Return

Notes

The headers User-Agent, Accept, and Content-Length are automatically included in the request.

Any additional request headers can be specified via headers, which should be a case-sensitive map of header name to header value.

If headers is provided (can be empty object), the raw response headers are inserted as a string under the key '_response'. The function :get_header() can be used to parse out a single header value from the raw response headers.

If method is empty and data is null then method becomes 'GET'. If data is not null then method becomes 'POST'.

Errors return an empty string.

Example

#do a GET request but also grab response headers h = {} r = web.req('https://api.iextrading.com/1.0/stock/aapl/company',null,h) print h._response #print response headers print r.parse_json() #pretty-print response body :dl(url,max_age) #

Download a file to the Axiom cache.

Parameters

Return

Notes

This uses the same cache as :import(), which is the folder .axiom.

This will show a progress bar while the file is downloading.

The the URL is already cached and the cache value is younger than max age, then no download occurs. (The cached file path is just returned.)

On error, the path is returned but the file will be empty.

:get(url,max_age) #

Get a URL with caching. Like :dl(), but returns response body instead of path of cached file.

Parameters

Return

Notes

This is equivalent to: io.load(web.dl(url))

Like :dl(), a progress bar is shown when a request actually occurs (cache miss).

:get_header(name,headers) #

Parse out the value of a single header from a string of raw headers.

Parameters

Return

:get_cookies(headers) #

Get cookies from raw response headers.

Parameters

Return

:submit(url,form) #

Do a HTML form submit (POST urlencoded form data).

Parameters

Return

Notes

This is equivalent to doing a form submit from an HTML form like:

<form action="url" method="POST"> <input name="key0" value="value0" /> <input name="key1" value="value1" /> ... </form>

Where keyN and valueN are key/value pairs in form.

:user_agent(name) #

Get or set user agent name.

Parameters

Return

Notes

The user agent is sent in all requests as part of the request header.

The default user agent is "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)", which imitates IE9 for maximum compatibility.

Example

print web.user_agent() #show current user agent web.user_agent('Python-urllib/2.6') #change user agent to mimic python

@server Functions

:use(on_request,on_upgrade,on_message) #

Set the global web server event handlers.

Parameters

Notes

All of the handlers take no parameters, and should use the other web.server functions to get context information.

By default (when the handlers are null) the on_request/on_message handlers echo back the request/message (for debugging), and on_upgrade closes the connection immediately (to deny unwanted websocket connections).

Example

#this is code for a simple chat server :on_request() if web.server.path()=='/' web.server.write_file('chat.html') else web.server.write_404() :on_upgrade() if web.server.path()=='/chat' web.server.subscribe('chat') else web.server.close() :on_message() if web.server.path()=='/chat' web.server.broadcast(['chat'],web.server.message()) web.server.use(on_request,on_upgrade,on_message) web.server.run({ port: 8999 })

See chat.html for the corresponding HTML/CSS/JS code.

:run(config) #

Run the global web server using specified configuration.

Parameters

Notes

The default config file (web.ini) looks like this:

;HTTP port. If TLS is enabled, positive numbers will redirect to HTTPS and negative number will mirror HTTPS port = 1234 ;Whether or not to bind to localhost only (vs binding to all adapters) local = true ;Secret used to sign cookies. Change this to invalidate previously signed cookies. Or share this in order for ; multiple servers to recognize the same cookies (if they are behind a load balancer, for example) secret = 12341234-1234-1234-1234-123412341234 ;Comment these in to enable TLS/SSL (HTTPS) ;tls_port = 443 ;tls_crt = server.crt ;tls_key = server.key

Except that "port" and "secret" are randomly generated.

Instead of a config file, an object can be passed containing all the necessary variables. At a bare minimum, the "port" variable is required, although it is recommended to specify "local" and "secret" as well.

The global web server handles two routes automatically:

Any route of the form "/static/*" will serve the corresponding file in the subdirectory named "static". Simply do not create a subdirectory named "static" if you do not want this behavior.

Any route of the form "/web/*" will serve the corresponding file in the directory specified by the environment variable "WEB", or the subdirectory named "web" if the environment variable does not exist. This feature is to facilitate sharing of client-side code between projects during development (via environment variable), while also allowing for deployments (via subdirectory). If the environment variable "WEB" is specified, it should contain an absolute path with no trailing slash. Simply do not create an environment variable named "WEB" and do not create a subfolder named "web" if you do not want this behavior.

This function blocks until the global web server is shut down (by ctrl-c or process signal/kill). This function should only be called from the main thread. Consider using background threads or processes if background processing is needed.

Example

#create a file called web.ini if not exist, and use those values #do nothing except serve files from /static/ and /web/ web.server.run() :method() #

Get the current request method.

Return

:path() #

Get the current request path.

Return

Notes

Excludes the querystring. Use :querystring() to get the querystring.

:content() #

Get the current request content (body).

Return

:querystring() #

Get the current request querystring.

Return

Notes

Excludes leading question mark. For example if the full path was "/asdf?xyz=123", the querystring would be "xyz=123".

Use :load_get() to parse the querystring.

:load_get(delimiter) #

Parse getdata from querystring.

Parameters

Return

:load_post() #

Parse postdata from request body.

Return

Notes

For files in multipart uploads, the key "[name].filename" is filename, "[name].type" is the content type, and "[name]" is the data.

:load_auth() #

Load and unscramble basic authorization header if specified

Return

Notes

Use :write_401() to force a login prompt in browsers.

:client_ip() #

Get the client IPv4 as a string.

Return

Notes

If the client IP is 127.0.0.1 (localhost), this function will look for the IP in the "X-Forwarded-For" header, in order to get the true client IP when behind a reverse proxy.

:pre(prefix) #

Checks if path matches prefix. If so, returns true and removes prefix from path.

Parameters

Return

Notes

This is used for routing. When returning true, path is modified, so subsequent calls to :path will be return different results.

Example

#map routes like "/abc/*" to files in subdirectory "xyz" :on_request() if web.server.pre('/abc/') web.server.write_file('xyz/'+web.server.path()) else web.server.write_404() web.server.use(on_request) web.server.run() :pop() #

Pop leftmost token off path until next slash. This modifies the path.

Return

Notes

This is used for routing. Tokens are defined as the strings in the path delimited by forward slashes. If there are no more tokens to pop, return empty string and also set path to empty string. (For example, if path is "/" and pop is called, path becomes "" and "" is returned.)

Example

#handle route like /[user]/[whatever] :on_request() user = web.server.pop() whatever = web.server.pop() web.server.write_json([user,whatever]) web.server.use(on_request) web.server.run() :get_header(name) #

Get header from current request by name.

Parameters

Return

:get_cookie(name) #

Get cookie from current request by name.

Parameters

Return

:set_cookie(name,value,domain) #

Set a response cookie.

Parameters

Notes

The domain flag is used to share cookies across subdomains. For example, if login.example.com wants to share cookies with api.example.com, set domain to true.

:wipe_cookie(name) #

Erase a response cookie from client.

Parameters

Notes

This tells the client to erase the cookie on its end by setting Max-Age to 0.

:get_signed_cookie(name) #

Get cookie from current request by name.

Parameters

Return

Notes

This uses the "secret" specified as part of the configuration for :run().

:set_signed_cookie(name,value,domain) #

Set a signed response cookie.

Parameters

Notes

The domain flag is used to share cookies across subdomains. For example, if login.example.com wants to share cookies with api.example.com, set domain to true.

This uses the "secret" specified as part of the configuration for :run().

:redirect(url,permanent) #

Write a redirect response.

Parameters

Notes

If permanent is true, the response status is "301 Moved Permanently". If permanent is false, the response status is "302 Found".

:write(response_headers,body) #

Write a response.

Parameters

Notes

This function provides low-level access for writing generic responses. It is recommended to use the other web.server.write_ functions for convenience.

The response_headers field should contain the status line followed by the headers. Each line in response_headers should be followed by "\r\n". However, the entire string should NOT contain a trailing "\r\n". (So response_headers end with "\r\n" not "\r\n\r\n".)

The "Content-Length" header is automatically added if not already present in response_headers.

The body is automatically ignored if responding to a HEAD request.

:write_200(content_type,data) #

Write a 200 OK response.

Parameters

:write_401(realm) #

Write a 401 Unauthorized response. This causes the browser to prompt for Basic Authorization.

Parameters

Notes

Although the specs say "401 Unauthorized", most other servers return "401 Not Authorized", so this function does the same.

:write_403() #

Write a 403 Forbidden response.

:write_404() #

Write a 404 Not Found response.

:write_405(methods) #

Write a 405 Method Not Allowed response.

Parameters

:write_500() #

Write a 500 Internal Server Error response.

:write_file(path,content_type) #

Write a 200 OK response using a file.

Parameters

Notes

If content_type is blank, it is automatically chosen based on the file extension in path.

:write_json(data) #

Write a 200 OK response with type "application/json" using any variable.

Parameters

Notes

The data parameter can be a variable of any type, and is automatically converted to JSON for the response.

In order to facilitate API development, this function automatically adds the response header "Access-Control-Allow-Origin: *", which allows for cross-origin requests (but not cross-origin credentials). It is recommended to use an API token instead of cross-origin credentials.

See this article for more information: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

:write_thread(fn,self,args,content_type) #

Write a 200 OK response after running a function in a separate thread.

Parameters

Notes

Use this function for long-running responses so that they do not block the main thread (and other connections) from processing.

This operates by creating a new thread, then calling fn with self and args in the new thread. After the function completes, the return value of the function is used as the response body, and content_type is used as the Content-Type header.

:minify_js(path) #

Minify Javascript file and return minified contents.

Parameters

Return

Notes

This function just removes comments and whitespace. It does not rename function or variable names.

:minify_css(path) #

Minify CSS file and return minified contents.

Parameters

Return

Notes

This function just removes comments and whitespace. It does not rename any selectors.

:render_html(path,context) #

Render an HTML template and return the rendered contents.

Parameters

Return

Notes

This function uses an extremely simple template syntax, where $variable is replaced with context[variable]. Use $$ to escape $. The variable $this becomes the filename from path without the extension, to aid with scoping.

The template syntax also supports server-side includes in the following format:

<!--#include path.html title="Title" name="value"-->

Where "path.html" is the path of the file to include (also treated like a template), and any attributes are used to form the context for the sub-template.

:html_escape(s) #

HTML-escape a string.

Parameters

Return

Notes

This simply replaces '<', '>', '&', and '"' with their corresponding HTML entities.

:close() #

Close the websocket.

:message() #

Get the current websocket message from the client to the server.

Return

:send_message(msg) #

Send a websocket message from the server to the client.

Parameters

:subscribe(channel) #

Subscribe the current websocket to channel. This causes messages :broadcast() to the channel to be relayed to websocket client.

Parameters

:broadcast(channels,msg) #

Broadcast a message to all specified channels.

Parameters