Uploading files to the server

PUT Method

Preliminaries

This note provides supplementary information about the server's implementation of the standard HTTP PUT method to create and update an entire resource.

The PUT method is used by WebDAV software and interactive AJAX calls to request the server to create or replace a resource. If replacing only a portion of a resource, the PATCH method is more appropriate.

When used in an AJAX call, a software developer must write a custom module with a handler to carry out the request (presumably via some type of server database), and the webmaster must configure a dynamic route with *methods=PUT which references that module.

When used with WebDAV software, the server will follow the predefined steps below to create or replace the static resource located at the requested path (relative to the website's document-root).

Request/response handlers

The server's request/response cycle for PUT requests is fulfilled using this sequence of handlers:

Request Handler Optional Configurable
1 Server Name Indication no no
2 Hosts no yes
3 IP Access yes yes
4 Resource Masks yes yes
5 Raw Path no no
6 Cookies no no
7 Forbidden yes yes
8 Cross Origin yes yes
9 RBAC yes yes
10 Content Range(Put) * no no
11 Content Length (Put) no no
12 Content Types (Put) no no
13 If Unmodified Since (Put) no no
14 Content Decoding (Put) no no
Dynamic Handler Optional Configurable
15 Router yes yes
Response Handler Optional Configurable
16 File Permissions no no
17 Etag yes no
18 Content Location no no
19 Content Length no no
20 Status Codes no yes

PUT processing is the inverse corollary of GET processing. The five handlers identified with the (Put) suffix, use the "request" side of the request/response cycle to perform steps that are similar to, but the inverse of, the similarly-named "response" steps performed with GET.

* The Content Range handler merely enforces the requirement that ranges are not allowed.

Permissions

The RBAC module is used to grant or deny permission to PUT static files. If the RBAC module is not on, the request will fail.

The server's file system must permit reads and writes by the server process to the area within the public directory which is the target of the request. The request will fail with status code 409 and an information header of rw-path will be returned with this type of unsuccessful response. The information header will provide one of these reasons for the denial:

  • 'mkdir failed' to indicate that the resource path's directory could not be created in the configured public directory.
  • 'write permission' to indicate that the existing file or parent directory is not writable by the server's process.
  • 'not directory' to indicate an attempt to create a new file subordinate to an existing file.

Content type

PUT requests must contain a content-type header containing a MIME type that is configured for the server. The request will fail with a status code of 415 and one of these information headers if the file being uploaded is not acceptable:

  • rw-content-type-missing is added if the request does not include a content-type header.
  • rw-content-type-not-supported is added if the filename's extension is not specified in the configuration's content-types section.
  • rw-content-type-mismatch is added if the request's content-type header does not match the configured MIME-type for the filename's extension, as specified in the configuration's content-types section.

Content length

PUT requests must contain a content-length header. If not present, the request will fail with a status code of 411 and an information header of rw-content-length-missing.

The maximum size of a file to be uploaded is limited by the server to the size configured in restrictions/content-length-limit. If the file is too large, the request will fail with a status code of 411 and an information header of rw-content-length-limit.

Synchronization

PUT requests may include an if-unmodified-since header. When present, the file will only be uploaded if it is a new file, or if the timestamp provided in the header is newer than the timestamp of the existing file.

Attempts to upload a file that is older than the one on the server will fail with a status code of 412 and an information header of rw-if-unmodified-since.

A better alternative to the if-unmodified-since header is the use of Etags. When an if-match or if-none-match header is present, the file will only be uploaded if the Etag value of the header matches the Etag of the server's existing file. When uploading a new file the request header's Etag value should be '*'.

Attempts to upload a file with an Etag that doesn't match the one on the server will fail with a status code of 412 and an information header of rw-if-match or rw-if-none-match.

Content encoding

PUT requests may be uploaded in compressed form if the request includes an acceptable content-encoding header with a value of 'gzip' or 'deflate'. The uploaded file will be decompressed and stored in the public directory in uncompressed form.

The request will fail with status code 406 if the Content Encoding module is not enabled or if the encoding value is not acceptable. An rw-content-decoding information header is added to this type of unsuccessful response.

Content range

The content-range request header is not allowed on PUT requests. If present, the request will fail with a status code 501 and the information header rw-content-range.

Success

Successful requests return one of two possible status codes: 201 is returned when a new file is created on the server, and 204 is returned when an existing file is replaced.

Successful responses include a content-location header confirming the file's location on the server.

For reference purposes, refer to IETF RFC 7231 Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content section 4.3.4 for the basic protocol expected of HTTP PUT requests.

Cookbook

Example: Enabling WebDAV PUT through RBAC
host {
modules {
rbac on
}
plugins {
router {
`/login-logout/*` *methods=POST *plugin='rwserve-rbac-auth'
}
}
rbac {
roles `/etc/rwserve/roles` // the file created by the 'addrole' CLI utility
cipher-secret C#9fB$2gD@5zR*7e // secret used to encrypt the 'rw-roles' cookie
max-idle 1800 // number of seconds of inactivity before credentials expire
resources {
`/login-logout/*` *methods=POST *roles=anonymous
`*` *methods=GET,HEAD *roles=anonymous
`*` *methods=PUT,DELETE *roles=devops
}
}
}

Uploading files to the server