Mercurial > hg > orthanc
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); |