| 732 | |
| 733 | |
| 734 | static Future<MessageEvent*> parse(const Request& request) |
| 735 | { |
| 736 | // TODO(benh): Do better error handling (to deal with a malformed |
| 737 | // libprocess message, malicious or otherwise). |
| 738 | |
| 739 | // First try and determine 'from'. |
| 740 | Option<UPID> from = None(); |
| 741 | |
| 742 | if (request.headers.contains("Libprocess-From")) { |
| 743 | from = UPID(strings::trim(request.headers.at("Libprocess-From"))); |
| 744 | } else { |
| 745 | // Try and get 'from' from the User-Agent. |
| 746 | const string& agent = request.headers.at("User-Agent"); |
| 747 | const string identifier = "libprocess/"; |
| 748 | size_t index = agent.find(identifier); |
| 749 | if (index != string::npos) { |
| 750 | from = UPID(agent.substr(index + identifier.size(), agent.size())); |
| 751 | } |
| 752 | } |
| 753 | |
| 754 | if (from.isNone()) { |
| 755 | return Failure("Failed to determine sender from request headers"); |
| 756 | } |
| 757 | |
| 758 | // Check that URL path is present and starts with '/'. |
| 759 | if (request.url.path.find('/') != 0) { |
| 760 | return Failure("Request URL path must start with '/'"); |
| 761 | } |
| 762 | |
| 763 | // Now determine 'to'. |
| 764 | size_t index = request.url.path.find('/', 1); |
| 765 | index = index != string::npos ? index - 1 : string::npos; |
| 766 | |
| 767 | // Decode possible percent-encoded 'to'. |
| 768 | Try<string> decode = http::decode(request.url.path.substr(1, index)); |
| 769 | |
| 770 | if (decode.isError()) { |
| 771 | return Failure("Failed to decode URL path: " + decode.error()); |
| 772 | } |
| 773 | |
| 774 | const UPID to(decode.get(), __address__); |
| 775 | |
| 776 | // And now determine 'name'. |
| 777 | index = index != string::npos ? index + 2: request.url.path.size(); |
| 778 | const string name = request.url.path.substr(index); |
| 779 | |
| 780 | VLOG(2) << "Parsed message name '" << name |
| 781 | << "' for " << to << " from " << from.get(); |
| 782 | |
| 783 | CHECK_SOME(request.reader); |
| 784 | http::Pipe::Reader reader = request.reader.get(); // Remove const. |
| 785 | |
| 786 | return reader.readAll() |
| 787 | .then([from, name, to](const string& body) { |
| 788 | Message message; |
| 789 | message.name = name; |
| 790 | message.from = from.get(); |
| 791 | message.to = to; |