]> git.proxmox.com Git - ceph.git/blame - ceph/src/seastar/src/http/response_parser.rl
import quincy beta 17.1.0
[ceph.git] / ceph / src / seastar / src / http / response_parser.rl
CommitLineData
11fdf7f2
TL
1/*
2 * This file is open source software, licensed to you under the terms
3 * of the Apache License, Version 2.0 (the "License"). See the NOTICE file
4 * distributed with this work for additional information regarding copyright
5 * ownership. You may not use this file except in compliance with the License.
6 *
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing,
12 * software distributed under the License is distributed on an
13 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 * KIND, either express or implied. See the License for the
15 * specific language governing permissions and limitations
16 * under the License.
17 */
18/*
19 * Copyright (C) 2015 Cloudius Systems, Ltd.
20 */
21
22#include <seastar/core/ragel.hh>
23#include <memory>
24#include <unordered_map>
25
26namespace seastar {
27
28struct http_response {
29 sstring _version;
30 std::unordered_map<sstring, sstring> _headers;
20effc67 31 int _status_code;
11fdf7f2
TL
32};
33
34%% machine http_response;
35
36%%{
37
38access _fsm_;
39
40action mark {
41 g.mark_start(p);
42}
43
44action store_version {
45 _rsp->_version = str();
46}
47
48action store_field_name {
49 _field_name = str();
50}
51
52action store_value {
53 _value = str();
54}
55
56action assign_field {
57 _rsp->_headers[_field_name] = std::move(_value);
58}
59
60action extend_field {
61 _rsp->_headers[_field_name] += sstring(" ") + std::move(_value);
62}
63
20effc67
TL
64action store_status {
65 _rsp->_status_code = std::atoi(str().c_str());
66}
67
11fdf7f2
TL
68action done {
69 done = true;
70 fbreak;
71}
72
73cr = '\r';
74lf = '\n';
75crlf = '\r\n';
76tchar = alpha | digit | '-' | '!' | '#' | '$' | '%' | '&' | '\'' | '*'
77 | '+' | '.' | '^' | '_' | '`' | '|' | '~';
78
79sp = ' ';
80ht = '\t';
81
82sp_ht = sp | ht;
83
84http_version = 'HTTP/' (digit '.' digit) >mark %store_version;
85
86field = tchar+ >mark %store_field_name;
87value = any* >mark %store_value;
20effc67
TL
88status_code = (digit digit digit) >mark %store_status;
89start_line = http_version space status_code space (any - cr - lf)* crlf;
11fdf7f2
TL
90header_1st = (field sp_ht* ':' value :> crlf) %assign_field;
91header_cont = (sp_ht+ value sp_ht* crlf) %extend_field;
92header = header_1st header_cont*;
93main := start_line header* :> (crlf @done);
94
95}%%
96
97class http_response_parser : public ragel_parser_base<http_response_parser> {
98 %% write data nofinal noprefix;
99public:
100 enum class state {
101 error,
102 eof,
103 done,
104 };
105 std::unique_ptr<http_response> _rsp;
106 sstring _field_name;
107 sstring _value;
108 state _state;
109public:
110 void init() {
111 init_base();
112 _rsp.reset(new http_response());
113 _state = state::eof;
114 %% write init;
115 }
116 char* parse(char* p, char* pe, char* eof) {
117 sstring_builder::guard g(_builder, p, pe);
118 auto str = [this, &g, &p] { g.mark_end(p); return get_str(); };
119 bool done = false;
120 if (p != pe) {
121 _state = state::error;
122 }
9f95a23c
TL
123#ifdef __clang__
124#pragma clang diagnostic push
125#pragma clang diagnostic ignored "-Wmisleading-indentation"
126#endif
11fdf7f2 127 %% write exec;
9f95a23c
TL
128#ifdef __clang__
129#pragma clang diagnostic pop
130#endif
11fdf7f2
TL
131 if (!done) {
132 p = nullptr;
133 } else {
134 _state = state::done;
135 }
136 return p;
137 }
138 auto get_parsed_response() {
139 return std::move(_rsp);
140 }
141 bool eof() const {
142 return _state == state::eof;
143 }
144};
145
146}