I wrote a patch to add OPTIONS as a supported HTTP method in Polipo. This arose out of the new use for the OPTIONS method for preflighted requests in HTTP access control (CORS), which is used when a XMLHttpRequest call across domain boundaries in reasonably current browsers (Chrome 4+, Firefox 3.5+, IE 10+) utilizes either
* a HTTP method other than GET, HEAD or POST * a content type other than plain text or form data * a custom request header. In my example, this occurs because a script on www.domain.com tries to query a JSON file on api.domain.com, which fails with a 501 at the moment when the page is requested via HTTP (obviously, it works over the tunneled connection when requested via HTTPS). See also: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests As per the spec (RFC 7231, section 4.3.7), responses to the OPTIONS method are not cacheable, so I added OPTIONS as an equal alternative to POST and PUT requests (especially since OPTIONS allows for an optional request body as well, although this is unheard of in the wild). This patch also could be easily extended to support the DELETE method used by some RESTful web services. https://github.com/jech/polipo/issues/26 --- client.c | 5 +++-- http.h | 1 + http_parse.c | 2 ++ polipo.texi | 10 +++++----- server.c | 4 +++- 5 files changed, 14 insertions(+), 8 deletions(-) diff --git a/client.c b/client.c index 58bb608..acb08f2 100644 --- a/client.c +++ b/client.c @@ -739,7 +739,7 @@ httpClientRequest(HTTPRequestPtr request, AtomPtr url) if(body_len < 0) { if(request->method == METHOD_GET || request->method == METHOD_HEAD || - request->method == METHOD_POST) + request->method == METHOD_POST || request->method == METHOD_OPTIONS) body_len = 0; } connection->bodylen = body_len; @@ -868,7 +868,8 @@ httpClientRequestContinue(int forbidden_code, AtomPtr url, httpLocalRequest : httpServerRequest; - if(request->method == METHOD_POST || request->method == METHOD_PUT) { + if(request->method == METHOD_POST || request->method == METHOD_PUT + || request->method == METHOD_OPTIONS) { do { object = findObject(OBJECT_HTTP, url->string, url->length); if(object) { diff --git a/http.h b/http.h index 2a06a5a..3771421 100644 --- a/http.h +++ b/http.h @@ -105,6 +105,7 @@ typedef struct _HTTPConnection { #define METHOD_CONNECT 3 #define METHOD_POST 4 #define METHOD_PUT 5 +#define METHOD_OPTIONS 6 #define REQUEST_SIDE(request) ((request)->method >= METHOD_POST) diff --git a/http_parse.c b/http_parse.c index a5940ff..20f376a 100644 --- a/http_parse.c +++ b/http_parse.c @@ -417,6 +417,8 @@ httpParseClientFirstLine(const char *restrict buf, int offset, method = METHOD_PUT; else if(y == x + 7 && memcmp(buf + x, "CONNECT", 7) == 0) method = METHOD_CONNECT; + else if(y == x + 7 && memcmp(buf + x, "OPTIONS", 7) == 0) + method = METHOD_OPTIONS; else method = METHOD_UNKNOWN; diff --git a/polipo.texi b/polipo.texi index 3f3adf4..1a1b0e5 100644 --- a/polipo.texi +++ b/polipo.texi @@ -305,10 +305,10 @@ resource with a different instance; it is typically used by web publishing applications. -@samp{POST} and @samp{PUT} requests are handled by Polipo pretty much -like @samp{GET} and @samp{HEAD}; however, for various reasons, some -precautions must be taken. In particular, any cached data for the -resource they refer to must be discarded, and they can never be +@samp{POST}, @samp{PUT} and @samp{OPTIONS} requests are handled by +Polipo pretty much like @samp{GET} and @samp{HEAD}; however, for various +reasons, some precautions must be taken. In particular, any cached data +for the resource they refer to must be discarded, and they can never be pipelined. Finally, HTTP/1.1 includes a convenient backdoor with the @@ -316,7 +316,7 @@ @ref{Tunnelling connections}. Polipo does not currently handle the more exotic methods such as -@samp{OPTIONS} and @samp{PROPFIND}. +@samp{PROPFIND}. @node Running, Network, Background, Top @chapter Running Polipo diff --git a/server.c b/server.c index e445d53..3e697a1 100644 --- a/server.c +++ b/server.c @@ -467,7 +467,8 @@ httpMakeServerRequest(char *name, int port, ObjectPtr object, return 1; } } else if(expectContinue >= 2 && server->version == HTTP_11) { - if(request->method == METHOD_POST || request->method == METHOD_PUT) + if(request->method == METHOD_POST || request->method == METHOD_PUT + || request->method == METHOD_OPTIONS) request->flags |= REQUEST_WAIT_CONTINUE; } @@ -1593,6 +1594,7 @@ httpWriteRequest(HTTPConnectionPtr connection, HTTPRequestPtr request, case METHOD_HEAD: m = "HEAD"; break; case METHOD_POST: m = "POST"; break; case METHOD_PUT: m = "PUT"; break; + case METHOD_OPTIONS: m = "OPTIONS"; break; default: abort(); } n = snnprintf(connection->reqbuf, n, bufsize, "%s ", m); ------------------------------------------------------------------------------ _______________________________________________ Polipo-users mailing list Polipo-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/polipo-users