Permalink
Browse files

src: support LINK/UNLINK (RFC 2068, draft-snell-link-method)

Add support for HTTP methods LINK and UNLINK originally defined in RFC2068
section 19.6.2.2, but with semantic added in a Internet draft.
https://tools.ietf.org/html/rfc2068#section-19.6.1.2
https://tools.ietf.org/html/draft-snell-link-method-12

Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Fedor Induty <fedor@indutny.com>
PR-URL: #267
  • Loading branch information...
1 parent e01811e commit e557b62744e4f487a303b25b27c56947d7a8bacc @dolmen dolmen committed with jasnell Oct 12, 2015
Showing with 81 additions and 12 deletions.
  1. +1 −0 AUTHORS
  2. +23 −12 http_parser.c
  3. +3 −0 http_parser.h
  4. +54 −0 test.c
View
@@ -65,3 +65,4 @@ Romain Giraud <giraud.romain@gmail.com>
Jay Satiro <raysatiro@yahoo.com>
Arne Steen <Arne.Steen@gmx.de>
Kjell Schubert <kjell.schubert@gmail.com>
+Olivier Mengué <dolmen@cpan.org>
View
@@ -965,7 +965,7 @@ size_t http_parser_execute (http_parser *parser,
case 'D': parser->method = HTTP_DELETE; break;
case 'G': parser->method = HTTP_GET; break;
case 'H': parser->method = HTTP_HEAD; break;
- case 'L': parser->method = HTTP_LOCK; break;
+ case 'L': parser->method = HTTP_LOCK; /* or LINK */ break;
case 'M': parser->method = HTTP_MKCOL; /* or MOVE, MKACTIVITY, MERGE, M-SEARCH, MKCALENDAR */ break;
case 'N': parser->method = HTTP_NOTIFY; break;
case 'O': parser->method = HTTP_OPTIONS; break;
@@ -975,7 +975,7 @@ size_t http_parser_execute (http_parser *parser,
case 'R': parser->method = HTTP_REPORT; /* or REBIND */ break;
case 'S': parser->method = HTTP_SUBSCRIBE; /* or SEARCH */ break;
case 'T': parser->method = HTTP_TRACE; break;
- case 'U': parser->method = HTTP_UNLOCK; /* or UNSUBSCRIBE, UNBIND */ break;
+ case 'U': parser->method = HTTP_UNLOCK; /* or UNSUBSCRIBE, UNBIND, UNLINK */ break;
default:
SET_ERRNO(HPE_INVALID_METHOD);
goto error;
@@ -1038,16 +1038,25 @@ size_t http_parser_execute (http_parser *parser,
SET_ERRNO(HPE_INVALID_METHOD);
goto error;
}
- } else if (parser->index == 1 && parser->method == HTTP_POST) {
- if (ch == 'R') {
- parser->method = HTTP_PROPFIND; /* or HTTP_PROPPATCH */
- } else if (ch == 'U') {
- parser->method = HTTP_PUT; /* or HTTP_PURGE */
- } else if (ch == 'A') {
- parser->method = HTTP_PATCH;
- } else {
- SET_ERRNO(HPE_INVALID_METHOD);
- goto error;
+ } else if (parser->index == 1) {
+ if (parser->method == HTTP_POST) {
+ if (ch == 'R') {
+ parser->method = HTTP_PROPFIND; /* or HTTP_PROPPATCH */
+ } else if (ch == 'U') {
+ parser->method = HTTP_PUT; /* or HTTP_PURGE */
+ } else if (ch == 'A') {
+ parser->method = HTTP_PATCH;
+ } else {
+ SET_ERRNO(HPE_INVALID_METHOD);
+ goto error;
+ }
+ } else if (parser->method == HTTP_LOCK) {
+ if (ch == 'I') {
+ parser->method = HTTP_LINK;
+ } else {
+ SET_ERRNO(HPE_INVALID_METHOD);
+ goto error;
+ }
}
} else if (parser->index == 2) {
if (parser->method == HTTP_PUT) {
@@ -1072,6 +1081,8 @@ size_t http_parser_execute (http_parser *parser,
}
} else if (parser->index == 4 && parser->method == HTTP_PROPFIND && ch == 'P') {
parser->method = HTTP_PROPPATCH;
+ } else if (parser->index == 3 && parser->method == HTTP_UNLOCK && ch == 'I') {
+ parser->method = HTTP_UNLINK;
} else {
SET_ERRNO(HPE_INVALID_METHOD);
goto error;
View
@@ -124,6 +124,9 @@ typedef int (*http_cb) (http_parser*);
XX(29, PURGE, PURGE) \
/* CalDAV */ \
XX(30, MKCALENDAR, MKCALENDAR) \
+ /* RFC-2068, section 19.6.1.2 */ \
+ XX(31, LINK, LINK) \
+ XX(32, UNLINK, UNLINK) \
enum http_method
{
View
@@ -1101,6 +1101,58 @@ const struct message requests[] =
,.body= ""
}
+/* Examples from the Internet draft for LINK/UNLINK methods:
+ * https://tools.ietf.org/id/draft-snell-link-method-01.html#rfc.section.5
+ */
+
+#define LINK_REQUEST 40
+, {.name = "link request"
+ ,.type= HTTP_REQUEST
+ ,.raw= "LINK /images/my_dog.jpg HTTP/1.1\r\n"
+ "Host: example.com\r\n"
+ "Link: <http://example.com/profiles/joe>; rel=\"tag\"\r\n"
+ "Link: <http://example.com/profiles/sally>; rel=\"tag\"\r\n"
+ "\r\n"
+ ,.should_keep_alive= TRUE
+ ,.message_complete_on_eof= FALSE
+ ,.http_major= 1
+ ,.http_minor= 1
+ ,.method= HTTP_LINK
+ ,.request_path= "/images/my_dog.jpg"
+ ,.request_url= "/images/my_dog.jpg"
+ ,.query_string= ""
+ ,.fragment= ""
+ ,.num_headers= 3
+ ,.headers= { { "Host", "example.com" }
+ , { "Link", "<http://example.com/profiles/joe>; rel=\"tag\"" }
+ , { "Link", "<http://example.com/profiles/sally>; rel=\"tag\"" }
+ }
+ ,.body= ""
+ }
+
+#define UNLINK_REQUEST 41
+, {.name = "link request"
+ ,.type= HTTP_REQUEST
+ ,.raw= "UNLINK /images/my_dog.jpg HTTP/1.1\r\n"
+ "Host: example.com\r\n"
+ "Link: <http://example.com/profiles/sally>; rel=\"tag\"\r\n"
+ "\r\n"
+ ,.should_keep_alive= TRUE
+ ,.message_complete_on_eof= FALSE
+ ,.http_major= 1
+ ,.http_minor= 1
+ ,.method= HTTP_UNLINK
+ ,.request_path= "/images/my_dog.jpg"
+ ,.request_url= "/images/my_dog.jpg"
+ ,.query_string= ""
+ ,.fragment= ""
+ ,.num_headers= 2
+ ,.headers= { { "Host", "example.com" }
+ , { "Link", "<http://example.com/profiles/sally>; rel=\"tag\"" }
+ }
+ ,.body= ""
+ }
+
, {.name= NULL } /* sentinel */
};
@@ -3760,6 +3812,8 @@ main (void)
"PATCH",
"PURGE",
"MKCALENDAR",
+ "LINK",
+ "UNLINK",
0 };
const char **this_method;
for (this_method = all_methods; *this_method; this_method++) {

0 comments on commit e557b62

Please sign in to comment.