From 4345e6b43447fd56213190b31e3ced2af1829f2d Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 1 Apr 2021 12:07:44 +0200 Subject: fix spec compliance for 405 reply, handle OPTIONS request with asterisk-form (RFC 7230, section 5.3.4) --- src/exchange/taler-exchange-httpd.c | 69 +++++++++++++++++++++++++++++++++---- 1 file changed, 62 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/exchange/taler-exchange-httpd.c b/src/exchange/taler-exchange-httpd.c index 3b8d6ed82..917b686e0 100644 --- a/src/exchange/taler-exchange-httpd.c +++ b/src/exchange/taler-exchange-httpd.c @@ -966,13 +966,19 @@ handle_mhd_request (void *cls, return ret; } + if ( (0 == strcasecmp (method, + MHD_HTTP_METHOD_OPTIONS)) && + (0 == strcmp ("*", + url)) ) + return TALER_MHD_reply_cors_preflight (connection); + if (0 == strcasecmp (method, MHD_HTTP_METHOD_HEAD)) method = MHD_HTTP_METHOD_GET; /* treat HEAD as GET here, MHD will do the rest */ /* parse first part of URL */ { - int found = GNUNET_NO; + bool found = false; size_t tok_size; const char *tok; const char *rest; @@ -1000,7 +1006,7 @@ handle_mhd_request (void *cls, tok_size)) || (tok_size != strlen (rh->url) ) ) continue; - found = GNUNET_YES; + found = true; /* The URL is a match! What we now do depends on the method. */ if (0 == strcasecmp (method, MHD_HTTP_METHOD_OPTIONS)) { @@ -1027,14 +1033,63 @@ handle_mhd_request (void *cls, } } - if (GNUNET_YES == found) + if (found) { /* we found a matching address, but the method is wrong */ + struct MHD_Response *reply; + MHD_RESULT ret; + char *allowed = NULL; + GNUNET_break_op (0); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_METHOD_NOT_ALLOWED, - TALER_EC_GENERIC_METHOD_INVALID, - method); + for (unsigned int i = 0; NULL != handlers[i].url; i++) + { + struct TEH_RequestHandler *rh = &handlers[i]; + + if ( (0 != strncmp (tok, + rh->url, + tok_size)) || + (tok_size != strlen (rh->url) ) ) + continue; + if (NULL == allowed) + { + allowed = GNUNET_strdup (rh->method); + } + else + { + char *tmp; + + GNUNET_asprintf (&tmp, + "%s, %s", + allowed, + rh->method); + GNUNET_free (allowed); + allowed = tmp; + } + if (0 == strcasecmp (rh->method, + MHD_HTTP_METHOD_GET)) + { + char *tmp; + + GNUNET_asprintf (&tmp, + "%s, %s", + allowed, + MHD_HTTP_METHOD_HEAD); + GNUNET_free (allowed); + allowed = tmp; + } + } + reply = TALER_MHD_make_error (TALER_EC_GENERIC_METHOD_INVALID, + method); + GNUNET_break (MHD_YES == + MHD_add_response_header (reply, + MHD_HTTP_HEADER_ALLOW, + allowed)); + GNUNET_free (allowed); + ret = MHD_queue_response (connection, + MHD_HTTP_METHOD_NOT_ALLOWED, + reply); + MHD_destroy_response (reply); + return ret; } } -- cgit v1.2.3