comparison Core/HttpServer/MongooseServer.cpp @ 414:26290b46056b

http method faking
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 03 May 2013 21:57:32 +0200
parents 63f707278fc8
children d558fa565c42
comparison
equal deleted inserted replaced
413:47d63c941902 414:26290b46056b
483 return decoded.substr(0, semicolons); 483 return decoded.substr(0, semicolons);
484 } 484 }
485 } 485 }
486 486
487 487
488 static bool ExtractMethod(Orthanc_HttpMethod& method,
489 const struct mg_request_info *request,
490 const HttpHandler::Arguments& headers,
491 const HttpHandler::Arguments& argumentsGET)
492 {
493 std::string overriden;
494
495 // Check whether some PUT/DELETE faking is done
496
497 // 1. Faking with Google's approach
498 HttpHandler::Arguments::const_iterator methodOverride =
499 headers.find("x-http-method-override");
500
501 if (methodOverride != headers.end())
502 {
503 overriden = methodOverride->second;
504 }
505 else if (!strcmp(request->request_method, "GET"))
506 {
507 // 2. Faking with Ruby on Rail's approach
508 // GET /my/resource?_method=delete <=> DELETE /my/resource
509 methodOverride = argumentsGET.find("_method");
510 if (methodOverride != argumentsGET.end())
511 {
512 overriden = methodOverride->second;
513 }
514 }
515
516 if (overriden.size() > 0)
517 {
518 // A faking has been done within this request
519 Toolbox::ToUpperCase(overriden);
520
521 if (overriden == "PUT")
522 {
523 method = Orthanc_HttpMethod_Put;
524 }
525 else if (overriden == "DELETE")
526 {
527 method = Orthanc_HttpMethod_Delete;
528 }
529 else
530 {
531 return false;
532 }
533 }
534
535 // No PUT/DELETE faking was present
536 if (!strcmp(request->request_method, "GET"))
537 {
538 method = Orthanc_HttpMethod_Get;
539 }
540 else if (!strcmp(request->request_method, "POST"))
541 {
542 method = Orthanc_HttpMethod_Post;
543 }
544 else if (!strcmp(request->request_method, "DELETE"))
545 {
546 method = Orthanc_HttpMethod_Delete;
547 }
548 else if (!strcmp(request->request_method, "PUT"))
549 {
550 method = Orthanc_HttpMethod_Put;
551 }
552 else
553 {
554 return false;
555 }
556
557 return true;
558 }
559
560
488 561
489 static void* Callback(enum mg_event event, 562 static void* Callback(enum mg_event event,
490 struct mg_connection *connection, 563 struct mg_connection *connection,
491 const struct mg_request_info *request) 564 const struct mg_request_info *request)
492 { 565 {
493 if (event == MG_NEW_REQUEST) 566 if (event == MG_NEW_REQUEST)
494 { 567 {
495 MongooseServer* that = (MongooseServer*) (request->user_data); 568 MongooseServer* that = (MongooseServer*) (request->user_data);
496 MongooseOutput output(connection); 569 MongooseOutput output(connection);
497 570
498 // Compute the method 571
499 Orthanc_HttpMethod method; 572 // Check remote calls
500 if (!strcmp(request->request_method, "GET"))
501 {
502 method = Orthanc_HttpMethod_Get;
503 }
504 else if (!strcmp(request->request_method, "POST"))
505 {
506 method = Orthanc_HttpMethod_Post;
507 }
508 else if (!strcmp(request->request_method, "DELETE"))
509 {
510 method = Orthanc_HttpMethod_Delete;
511 }
512 else if (!strcmp(request->request_method, "PUT"))
513 {
514 method = Orthanc_HttpMethod_Put;
515 }
516 else
517 {
518 output.SendHeader(Orthanc_HttpStatus_405_MethodNotAllowed);
519 return (void*) "";
520 }
521
522 if (!that->IsRemoteAccessAllowed() && 573 if (!that->IsRemoteAccessAllowed() &&
523 request->remote_ip != LOCALHOST) 574 request->remote_ip != LOCALHOST)
524 { 575 {
525 SendUnauthorized(output); 576 SendUnauthorized(output);
526 return (void*) ""; 577 return (void*) "";
527 } 578 }
528 579
529 HttpHandler::Arguments arguments, headers; 580
530 581 // Extract the HTTP headers
582 HttpHandler::Arguments headers;
531 for (int i = 0; i < request->num_headers; i++) 583 for (int i = 0; i < request->num_headers; i++)
532 { 584 {
533 std::string name = request->http_headers[i].name; 585 std::string name = request->http_headers[i].name;
534 std::transform(name.begin(), name.end(), name.begin(), ::tolower); 586 std::transform(name.begin(), name.end(), name.begin(), ::tolower);
535 headers.insert(std::make_pair(name, request->http_headers[i].value)); 587 headers.insert(std::make_pair(name, request->http_headers[i].value));
536 } 588 }
589
590
591 // Extract the GET arguments
592 HttpHandler::Arguments argumentsGET;
593 if (!strcmp(request->request_method, "GET"))
594 {
595 HttpHandler::ParseGetQuery(argumentsGET, request->query_string);
596 }
597
598
599 // Compute the HTTP method, taking method faking into consideration
600 Orthanc_HttpMethod method;
601 if (!ExtractMethod(method, request, headers, argumentsGET))
602 {
603 output.SendHeader(Orthanc_HttpStatus_405_MethodNotAllowed);
604 return (void*) "";
605 }
606
537 607
538 // Authenticate this connection 608 // Authenticate this connection
539 if (that->IsAuthenticationEnabled() && 609 if (that->IsAuthenticationEnabled() &&
540 !Authorize(*that, headers, output)) 610 !Authorize(*that, headers, output))
541 { 611 {
562 return (void*) ""; 632 return (void*) "";
563 } 633 }
564 } 634 }
565 635
566 636
567 std::string postData; 637 // Extract the body of the request for PUT and POST
568 638 std::string body;
569 if (method == Orthanc_HttpMethod_Get) 639 if (method == Orthanc_HttpMethod_Post ||
570 { 640 method == Orthanc_HttpMethod_Put)
571 HttpHandler::ParseGetQuery(arguments, request->query_string);
572 }
573 else if (method == Orthanc_HttpMethod_Post ||
574 method == Orthanc_HttpMethod_Put)
575 { 641 {
576 HttpHandler::Arguments::const_iterator ct = headers.find("content-type"); 642 HttpHandler::Arguments::const_iterator ct = headers.find("content-type");
577 if (ct == headers.end()) 643 if (ct == headers.end())
578 { 644 {
579 output.SendHeader(Orthanc_HttpStatus_400_BadRequest); 645 output.SendHeader(Orthanc_HttpStatus_400_BadRequest);
584 650
585 std::string contentType = ct->second; 651 std::string contentType = ct->second;
586 if (contentType.size() >= multipartLength && 652 if (contentType.size() >= multipartLength &&
587 !memcmp(contentType.c_str(), multipart, multipartLength)) 653 !memcmp(contentType.c_str(), multipart, multipartLength))
588 { 654 {
589 status = ParseMultipartPost(postData, connection, headers, contentType, that->GetChunkStore()); 655 status = ParseMultipartPost(body, connection, headers, contentType, that->GetChunkStore());
590 } 656 }
591 else 657 else
592 { 658 {
593 status = ReadPostData(postData, connection, headers); 659 status = ReadPostData(body, connection, headers);
594 } 660 }
595 661
596 switch (status) 662 switch (status)
597 { 663 {
598 case PostDataStatus_NoLength: 664 case PostDataStatus_NoLength:
610 default: 676 default:
611 break; 677 break;
612 } 678 }
613 } 679 }
614 680
681
682 // Call the proper handler for this URI
615 UriComponents uri; 683 UriComponents uri;
616 Toolbox::SplitUriComponents(uri, request->uri); 684 Toolbox::SplitUriComponents(uri, request->uri);
617 685
618 HttpHandler* handler = that->FindHandler(uri); 686 HttpHandler* handler = that->FindHandler(uri);
619 if (handler) 687 if (handler)
620 { 688 {
621 try 689 try
622 { 690 {
623 handler->Handle(output, method, uri, headers, arguments, postData); 691 handler->Handle(output, method, uri, headers, argumentsGET, body);
624 } 692 }
625 catch (OrthancException& e) 693 catch (OrthancException& e)
626 { 694 {
627 LOG(ERROR) << "MongooseServer Exception [" << e.What() << "]"; 695 LOG(ERROR) << "MongooseServer Exception [" << e.What() << "]";
628 output.SendHeader(Orthanc_HttpStatus_500_InternalServerError); 696 output.SendHeader(Orthanc_HttpStatus_500_InternalServerError);