1 module HttpBenchmark; 2 3 import test.codec.common; 4 import hunt.http.codec.http.decode.HttpParser; 5 import hunt.http.codec.http.model; 6 // import hunt.http.codec.http.model.HttpComplianceSection; 7 8 import hunt.Exceptions; 9 import hunt.text.Charset; 10 11 import hunt.io.BufferUtils; 12 import hunt.io.ByteBuffer; 13 import hunt.collection.ArrayList; 14 import hunt.collection.List; 15 16 import hunt.logging; 17 18 import std.conv; 19 import std.range; 20 import std.stdio; 21 22 alias State = HttpParser.State; 23 24 25 class HttpBenchmark { 26 27 private string _host; 28 private int _port; 29 private string _bad; 30 private string _content; 31 private string _methodOrVersion; 32 private string _uriOrStatus; 33 private string _versionOrReason; 34 private List!HttpField _fields; 35 private List!HttpField _trailers; 36 private string[] _hdr; 37 private string[] _val; 38 private int _headers; 39 private bool _early; 40 private bool _headerCompleted; 41 private bool _messageCompleted; 42 private List!HttpComplianceSection _complianceViolation; 43 44 this() { 45 _fields = new ArrayList!HttpField(); 46 _trailers = new ArrayList!HttpField(); 47 _complianceViolation = new ArrayList!HttpComplianceSection(); 48 HttpParser.RequestHandler handler = new Handler(); 49 parser = new HttpParser(handler); 50 } 51 private HttpParser parser; 52 53 void benchmark(int number = 10) { 54 import core.time; 55 import std.datetime; 56 import hunt.util.DateTime; 57 MonoTime startTime = MonoTime.currTime; 58 foreach(j ; 0..number) { 59 testParseRequest(); 60 } 61 Duration timeElapsed = MonoTime.currTime - startTime; 62 size_t t = timeElapsed.total!(TimeUnit.Microsecond)(); 63 tracef("time consuming (%d), total: %d microseconds, avg: %d microseconds", number, t, t/number); 64 } 65 66 void initialize() { 67 _bad = null; 68 _host = null; 69 _content = null; 70 _methodOrVersion = null; 71 _uriOrStatus = null; 72 _versionOrReason = null; 73 _hdr = null; 74 _val = null; 75 _headers = 0; 76 _headerCompleted = false; 77 _messageCompleted = false; 78 _complianceViolation.clear(); 79 } 80 81 void testParseRequest() { 82 initialize(); 83 string str = `GET /plaintext HTTP/1.1 84 cache-control: no-cache 85 Postman-Token: f290cab4-ac2b-46c7-9db8-ca07f5758989 86 User-Agent: PostmanRuntime/7.4.0 87 Accept: */* 88 Host: 127.0.0.1:8080 89 accept-encoding: gzip, deflate 90 Connection: keep-alive 91 92 `; 93 ByteBuffer buffer = BufferUtils.toBuffer(str); 94 // HttpParser.RequestHandler handler = new Handler(); 95 // parser = new HttpParser(handler); 96 parser.parseNext(buffer); 97 parser.reset(); 98 } 99 100 101 private class Handler : HttpParser.RequestHandler, HttpParser.ResponseHandler, HttpParser.ComplianceHandler { 102 103 bool content(ByteBuffer buffer) { 104 if (_content == null) 105 _content = ""; 106 string c = BufferUtils.toString(buffer); 107 _content = _content ~ c; 108 buffer.position(buffer.limit()); 109 return false; 110 } 111 112 113 bool startRequest(string method, string uri, HttpVersion ver) { 114 version (HUNT_DEBUG) { 115 tracef("server received the request line, %s, %s, %s", method, uri, ver); 116 } 117 _fields.clear(); 118 _trailers.clear(); 119 _headers = -1; 120 _hdr = new string[10]; 121 _val = new string[10]; 122 _methodOrVersion = method; 123 _uriOrStatus = uri; 124 _versionOrReason = ver == HttpVersion.Null ? null : ver.asString(); 125 _messageCompleted = false; 126 _headerCompleted = false; 127 _early = false; 128 return false; 129 } 130 131 132 void parsedHeader(HttpField field) { 133 _fields.add(field); 134 _hdr[++_headers] = field.getName(); 135 _val[_headers] = field.getValue(); 136 137 if (typeid(field) == typeid(HostPortHttpField)) { 138 HostPortHttpField hpfield = cast(HostPortHttpField) field; 139 _host = hpfield.getHost(); 140 _port = hpfield.getPort(); 141 } 142 } 143 144 145 bool headerComplete() { 146 _content = null; 147 _headerCompleted = true; 148 return false; 149 } 150 151 152 void parsedTrailer(HttpField field) { 153 _trailers.add(field); 154 } 155 156 157 bool contentComplete() { 158 return false; 159 } 160 161 162 bool messageComplete() { 163 _messageCompleted = true; 164 return true; 165 } 166 167 168 void badMessage(BadMessageException failure) { 169 string reason = failure.getReason(); 170 _bad = reason.empty ? failure.getCode().to!string : reason; 171 } 172 173 void badMessage(int status, string reason) { 174 175 } 176 177 178 bool startResponse(HttpVersion ver, int status, string reason) { 179 _fields.clear(); 180 _trailers.clear(); 181 _methodOrVersion = ver.asString(); 182 _uriOrStatus = status.to!string; 183 _versionOrReason = reason; 184 _headers = -1; 185 _hdr = new string[10]; 186 _val = new string[10]; 187 _messageCompleted = false; 188 _headerCompleted = false; 189 return false; 190 } 191 192 193 void earlyEOF() { 194 _early = true; 195 } 196 197 198 int getHeaderCacheSize() { 199 return 512; 200 } 201 202 203 void onComplianceViolation(HttpCompliance compliance, HttpComplianceSection violation, string reason) { 204 _complianceViolation.add(violation); 205 } 206 } 207 }