aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/http
diff options
context:
space:
mode:
authorAnton Samokhvalov <pg83@yandex.ru>2022-02-10 16:45:17 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:45:17 +0300
commitd3a398281c6fd1d3672036cb2d63f842d2cb28c5 (patch)
treedd4bd3ca0f36b817e96812825ffaf10d645803f2 /library/cpp/http
parent72cb13b4aff9bc9cf22e49251bc8fd143f82538f (diff)
downloadydb-d3a398281c6fd1d3672036cb2d63f842d2cb28c5.tar.gz
Restoring authorship annotation for Anton Samokhvalov <pg83@yandex.ru>. Commit 2 of 2.
Diffstat (limited to 'library/cpp/http')
-rw-r--r--library/cpp/http/fetch/exthttpcodes.cpp364
-rw-r--r--library/cpp/http/fetch/exthttpcodes.h214
-rw-r--r--library/cpp/http/fetch/http_digest.cpp156
-rw-r--r--library/cpp/http/fetch/http_digest.h56
-rw-r--r--library/cpp/http/fetch/http_socket.cpp162
-rw-r--r--library/cpp/http/fetch/httpfetcher.h56
-rw-r--r--library/cpp/http/fetch/httpfsm.h58
-rw-r--r--library/cpp/http/fetch/httpfsm_ut.cpp118
-rw-r--r--library/cpp/http/fetch/httpheader.h110
-rw-r--r--library/cpp/http/fetch/httpload.cpp312
-rw-r--r--library/cpp/http/fetch/httpload.h264
-rw-r--r--library/cpp/http/fetch/httpparser.h94
-rw-r--r--library/cpp/http/fetch/httpparser_ut.cpp172
-rw-r--r--library/cpp/http/fetch/httpzreader.h42
-rw-r--r--library/cpp/http/fetch/library-htfetch_ut_hreflang_in.h304
-rw-r--r--library/cpp/http/fetch/ya.make12
-rw-r--r--library/cpp/http/io/chunk.cpp398
-rw-r--r--library/cpp/http/io/chunk.h38
-rw-r--r--library/cpp/http/io/chunk_ut.cpp72
-rw-r--r--library/cpp/http/io/compression.cpp58
-rw-r--r--library/cpp/http/io/compression.h26
-rw-r--r--library/cpp/http/io/compression_ut.cpp20
-rw-r--r--library/cpp/http/io/fuzz/main.cpp28
-rw-r--r--library/cpp/http/io/fuzz/ya.make20
-rw-r--r--library/cpp/http/io/headers.cpp106
-rw-r--r--library/cpp/http/io/headers.h126
-rw-r--r--library/cpp/http/io/headers_ut.cpp10
-rw-r--r--library/cpp/http/io/list_codings/main.cpp14
-rw-r--r--library/cpp/http/io/list_codings/ya.make24
-rw-r--r--library/cpp/http/io/stream.cpp1302
-rw-r--r--library/cpp/http/io/stream.h180
-rw-r--r--library/cpp/http/io/stream_ut.cpp294
-rw-r--r--library/cpp/http/io/stream_ut_medium.cpp94
-rw-r--r--library/cpp/http/io/ut/medium/ya.make12
-rw-r--r--library/cpp/http/io/ut/ya.make16
-rw-r--r--library/cpp/http/io/ya.make24
-rw-r--r--library/cpp/http/misc/httpcodes.cpp88
-rw-r--r--library/cpp/http/misc/httpcodes.h84
-rw-r--r--library/cpp/http/misc/httpdate.cpp16
-rw-r--r--library/cpp/http/misc/httpdate.h8
-rw-r--r--library/cpp/http/misc/httpdate_ut.cpp18
-rw-r--r--library/cpp/http/misc/httpreqdata.cpp260
-rw-r--r--library/cpp/http/misc/httpreqdata.h68
-rw-r--r--library/cpp/http/misc/httpreqdata_ut.cpp90
-rw-r--r--library/cpp/http/misc/parsed_request.cpp54
-rw-r--r--library/cpp/http/misc/parsed_request.h50
-rw-r--r--library/cpp/http/misc/parsed_request_ut.cpp48
-rw-r--r--library/cpp/http/misc/ut/ya.make18
-rw-r--r--library/cpp/http/misc/ya.make22
-rw-r--r--library/cpp/http/server/conn.cpp84
-rw-r--r--library/cpp/http/server/conn.h56
-rw-r--r--library/cpp/http/server/http.cpp566
-rw-r--r--library/cpp/http/server/http.h86
-rw-r--r--library/cpp/http/server/http_ex.cpp120
-rw-r--r--library/cpp/http/server/http_ex.h24
-rw-r--r--library/cpp/http/server/http_ut.cpp140
-rw-r--r--library/cpp/http/server/options.cpp44
-rw-r--r--library/cpp/http/server/options.h130
-rw-r--r--library/cpp/http/server/response.cpp32
-rw-r--r--library/cpp/http/server/response.h26
-rw-r--r--library/cpp/http/server/response_ut.cpp26
-rw-r--r--library/cpp/http/server/ut/ya.make4
-rw-r--r--library/cpp/http/server/ya.make28
63 files changed, 3773 insertions, 3773 deletions
diff --git a/library/cpp/http/fetch/exthttpcodes.cpp b/library/cpp/http/fetch/exthttpcodes.cpp
index baa2a2a0fd..acc05650c8 100644
--- a/library/cpp/http/fetch/exthttpcodes.cpp
+++ b/library/cpp/http/fetch/exthttpcodes.cpp
@@ -1,160 +1,160 @@
-#include "exthttpcodes.h"
-
+#include "exthttpcodes.h"
+
#include <cstring>
-const ui16 CrazyServer = ShouldDelete | MarkSuspect;
+const ui16 CrazyServer = ShouldDelete | MarkSuspect;
-struct http_flag {
- ui16 http;
- ui16 flag;
-};
+struct http_flag {
+ ui16 http;
+ ui16 flag;
+};
static http_flag HTTP_FLAG[] = {
- {HTTP_CONTINUE, MarkSuspect}, // 100
- {HTTP_SWITCHING_PROTOCOLS, CrazyServer}, // 101
- {HTTP_PROCESSING, CrazyServer}, // 102
+ {HTTP_CONTINUE, MarkSuspect}, // 100
+ {HTTP_SWITCHING_PROTOCOLS, CrazyServer}, // 101
+ {HTTP_PROCESSING, CrazyServer}, // 102
- {HTTP_OK, ShouldReindex}, // 200
- {HTTP_CREATED, CrazyServer}, // 201
- {HTTP_ACCEPTED, ShouldDelete}, // 202
- {HTTP_NON_AUTHORITATIVE_INFORMATION, ShouldReindex}, // 203
- {HTTP_NO_CONTENT, ShouldDelete}, // 204
- {HTTP_RESET_CONTENT, ShouldDelete}, // 205
- {HTTP_PARTIAL_CONTENT, ShouldReindex}, // 206
- {HTTP_MULTI_STATUS, CrazyServer}, // 207
- {HTTP_ALREADY_REPORTED, CrazyServer}, // 208
- {HTTP_IM_USED, CrazyServer}, // 226
+ {HTTP_OK, ShouldReindex}, // 200
+ {HTTP_CREATED, CrazyServer}, // 201
+ {HTTP_ACCEPTED, ShouldDelete}, // 202
+ {HTTP_NON_AUTHORITATIVE_INFORMATION, ShouldReindex}, // 203
+ {HTTP_NO_CONTENT, ShouldDelete}, // 204
+ {HTTP_RESET_CONTENT, ShouldDelete}, // 205
+ {HTTP_PARTIAL_CONTENT, ShouldReindex}, // 206
+ {HTTP_MULTI_STATUS, CrazyServer}, // 207
+ {HTTP_ALREADY_REPORTED, CrazyServer}, // 208
+ {HTTP_IM_USED, CrazyServer}, // 226
- {HTTP_MULTIPLE_CHOICES, CheckLinks | ShouldDelete}, // 300
- {HTTP_MOVED_PERMANENTLY, CheckLocation | ShouldDelete | MoveRedir}, // 301
- {HTTP_FOUND, CheckLocation | ShouldDelete | MoveRedir}, // 302
- {HTTP_SEE_OTHER, CheckLocation | ShouldDelete | MoveRedir}, // 303
- {HTTP_NOT_MODIFIED, 0}, // 304
- {HTTP_USE_PROXY, ShouldDelete}, // 305
- {HTTP_TEMPORARY_REDIRECT, CheckLocation | ShouldDelete | MoveRedir}, // 307
- {HTTP_PERMANENT_REDIRECT, CheckLocation | ShouldDelete | MoveRedir}, // 308
+ {HTTP_MULTIPLE_CHOICES, CheckLinks | ShouldDelete}, // 300
+ {HTTP_MOVED_PERMANENTLY, CheckLocation | ShouldDelete | MoveRedir}, // 301
+ {HTTP_FOUND, CheckLocation | ShouldDelete | MoveRedir}, // 302
+ {HTTP_SEE_OTHER, CheckLocation | ShouldDelete | MoveRedir}, // 303
+ {HTTP_NOT_MODIFIED, 0}, // 304
+ {HTTP_USE_PROXY, ShouldDelete}, // 305
+ {HTTP_TEMPORARY_REDIRECT, CheckLocation | ShouldDelete | MoveRedir}, // 307
+ {HTTP_PERMANENT_REDIRECT, CheckLocation | ShouldDelete | MoveRedir}, // 308
- {HTTP_BAD_REQUEST, CrazyServer}, // 400
- {HTTP_UNAUTHORIZED, ShouldDelete}, // 401
- {HTTP_PAYMENT_REQUIRED, ShouldDelete}, // 402
- {HTTP_FORBIDDEN, ShouldDelete}, // 403
- {HTTP_NOT_FOUND, ShouldDelete}, // 404
- {HTTP_METHOD_NOT_ALLOWED, ShouldDelete}, // 405
- {HTTP_NOT_ACCEPTABLE, ShouldDelete}, // 406
- {HTTP_PROXY_AUTHENTICATION_REQUIRED, CrazyServer}, // 407
- {HTTP_REQUEST_TIME_OUT, ShouldDisconnect | ShouldRetry | MarkSuspect}, // 408
- {HTTP_CONFLICT, MarkSuspect}, // 409
- {HTTP_GONE, ShouldDelete}, // 410
- {HTTP_LENGTH_REQUIRED, CrazyServer}, // 411
- {HTTP_PRECONDITION_FAILED, CrazyServer}, // 412
- {HTTP_REQUEST_ENTITY_TOO_LARGE, CrazyServer}, // 413
- {HTTP_REQUEST_URI_TOO_LARGE, ShouldDelete}, // 414
- {HTTP_UNSUPPORTED_MEDIA_TYPE, CrazyServer}, // 415
- {HTTP_REQUESTED_RANGE_NOT_SATISFIABLE, CrazyServer}, // 416
- {HTTP_EXPECTATION_FAILED, ShouldDelete}, // 417
- {HTTP_I_AM_A_TEAPOT, CrazyServer}, // 418
- {HTTP_AUTHENTICATION_TIMEOUT, ShouldDelete}, // 419
+ {HTTP_BAD_REQUEST, CrazyServer}, // 400
+ {HTTP_UNAUTHORIZED, ShouldDelete}, // 401
+ {HTTP_PAYMENT_REQUIRED, ShouldDelete}, // 402
+ {HTTP_FORBIDDEN, ShouldDelete}, // 403
+ {HTTP_NOT_FOUND, ShouldDelete}, // 404
+ {HTTP_METHOD_NOT_ALLOWED, ShouldDelete}, // 405
+ {HTTP_NOT_ACCEPTABLE, ShouldDelete}, // 406
+ {HTTP_PROXY_AUTHENTICATION_REQUIRED, CrazyServer}, // 407
+ {HTTP_REQUEST_TIME_OUT, ShouldDisconnect | ShouldRetry | MarkSuspect}, // 408
+ {HTTP_CONFLICT, MarkSuspect}, // 409
+ {HTTP_GONE, ShouldDelete}, // 410
+ {HTTP_LENGTH_REQUIRED, CrazyServer}, // 411
+ {HTTP_PRECONDITION_FAILED, CrazyServer}, // 412
+ {HTTP_REQUEST_ENTITY_TOO_LARGE, CrazyServer}, // 413
+ {HTTP_REQUEST_URI_TOO_LARGE, ShouldDelete}, // 414
+ {HTTP_UNSUPPORTED_MEDIA_TYPE, CrazyServer}, // 415
+ {HTTP_REQUESTED_RANGE_NOT_SATISFIABLE, CrazyServer}, // 416
+ {HTTP_EXPECTATION_FAILED, ShouldDelete}, // 417
+ {HTTP_I_AM_A_TEAPOT, CrazyServer}, // 418
+ {HTTP_AUTHENTICATION_TIMEOUT, ShouldDelete}, // 419
- {HTTP_MISDIRECTED_REQUEST, CrazyServer}, // 421
- {HTTP_UNPROCESSABLE_ENTITY, CrazyServer}, // 422
- {HTTP_LOCKED, ShouldDelete}, // 423
- {HTTP_FAILED_DEPENDENCY, CrazyServer}, // 424
- {HTTP_UPGRADE_REQUIRED, ShouldDelete}, // 426
- {HTTP_PRECONDITION_REQUIRED, ShouldDelete}, // 428
- {HTTP_TOO_MANY_REQUESTS, ShouldDisconnect | ShouldRetry | MarkSuspect}, // 429
- {HTTP_UNAVAILABLE_FOR_LEGAL_REASONS, ShouldDelete}, // 451
+ {HTTP_MISDIRECTED_REQUEST, CrazyServer}, // 421
+ {HTTP_UNPROCESSABLE_ENTITY, CrazyServer}, // 422
+ {HTTP_LOCKED, ShouldDelete}, // 423
+ {HTTP_FAILED_DEPENDENCY, CrazyServer}, // 424
+ {HTTP_UPGRADE_REQUIRED, ShouldDelete}, // 426
+ {HTTP_PRECONDITION_REQUIRED, ShouldDelete}, // 428
+ {HTTP_TOO_MANY_REQUESTS, ShouldDisconnect | ShouldRetry | MarkSuspect}, // 429
+ {HTTP_UNAVAILABLE_FOR_LEGAL_REASONS, ShouldDelete}, // 451
- {HTTP_INTERNAL_SERVER_ERROR, MarkSuspect}, // 500
- {HTTP_NOT_IMPLEMENTED, ShouldDelete | ShouldDisconnect}, // 501
- {HTTP_BAD_GATEWAY, MarkSuspect}, // 502
- {HTTP_SERVICE_UNAVAILABLE, ShouldDisconnect | ShouldRetry | MarkSuspect}, // 503
- {HTTP_GATEWAY_TIME_OUT, ShouldDisconnect | ShouldRetry | MarkSuspect}, // 504
- {HTTP_HTTP_VERSION_NOT_SUPPORTED, CrazyServer | ShouldDisconnect}, // 505
+ {HTTP_INTERNAL_SERVER_ERROR, MarkSuspect}, // 500
+ {HTTP_NOT_IMPLEMENTED, ShouldDelete | ShouldDisconnect}, // 501
+ {HTTP_BAD_GATEWAY, MarkSuspect}, // 502
+ {HTTP_SERVICE_UNAVAILABLE, ShouldDisconnect | ShouldRetry | MarkSuspect}, // 503
+ {HTTP_GATEWAY_TIME_OUT, ShouldDisconnect | ShouldRetry | MarkSuspect}, // 504
+ {HTTP_HTTP_VERSION_NOT_SUPPORTED, CrazyServer | ShouldDisconnect}, // 505
- {HTTP_VARIANT_ALSO_NEGOTIATES, CrazyServer | ShouldDisconnect}, // 506
- {HTTP_INSUFFICIENT_STORAGE, CrazyServer | ShouldDisconnect}, // 507
- {HTTP_LOOP_DETECTED, CrazyServer | ShouldDisconnect}, // 508
- {HTTP_BANDWIDTH_LIMIT_EXCEEDED, ShouldDisconnect | ShouldRetry | MarkSuspect}, // 509
- {HTTP_NOT_EXTENDED, ShouldDelete}, // 510
- {HTTP_NETWORK_AUTHENTICATION_REQUIRED, ShouldDelete}, // 511
+ {HTTP_VARIANT_ALSO_NEGOTIATES, CrazyServer | ShouldDisconnect}, // 506
+ {HTTP_INSUFFICIENT_STORAGE, CrazyServer | ShouldDisconnect}, // 507
+ {HTTP_LOOP_DETECTED, CrazyServer | ShouldDisconnect}, // 508
+ {HTTP_BANDWIDTH_LIMIT_EXCEEDED, ShouldDisconnect | ShouldRetry | MarkSuspect}, // 509
+ {HTTP_NOT_EXTENDED, ShouldDelete}, // 510
+ {HTTP_NETWORK_AUTHENTICATION_REQUIRED, ShouldDelete}, // 511
- // custom
- {HTTP_BAD_RESPONSE_HEADER, CrazyServer}, // 1000
- {HTTP_CONNECTION_LOST, ShouldRetry}, // 1001
- {HTTP_BODY_TOO_LARGE, ShouldDelete | CanBeFake}, // 1002
- {HTTP_ROBOTS_TXT_DISALLOW, ShouldDelete}, // 1003
- {HTTP_BAD_URL, ShouldDelete}, // 1004
- {HTTP_BAD_MIME, ShouldDelete}, // 1005
- {HTTP_DNS_FAILURE, ShouldDisconnect | MarkSuspect}, // 1006
- {HTTP_BAD_STATUS_CODE, CrazyServer}, // 1007
- {HTTP_BAD_HEADER_STRING, CrazyServer}, // 1008
- {HTTP_BAD_CHUNK, CrazyServer}, // 1009
- {HTTP_CONNECT_FAILED, ShouldDisconnect | ShouldRetry | MarkSuspect}, // 1010
- {HTTP_FILTER_DISALLOW, ShouldDelete}, // 1011
- {HTTP_LOCAL_EIO, ShouldRetry}, // 1012
- {HTTP_BAD_CONTENT_LENGTH, ShouldDelete}, // 1013
- {HTTP_BAD_ENCODING, ShouldDelete}, // 1014
- {HTTP_LENGTH_UNKNOWN, ShouldDelete}, // 1015
- {HTTP_HEADER_EOF, ShouldRetry | CanBeFake}, // 1016
- {HTTP_MESSAGE_EOF, ShouldRetry | CanBeFake}, // 1017
- {HTTP_CHUNK_EOF, ShouldRetry | CanBeFake}, // 1018
- {HTTP_PAST_EOF, ShouldRetry | ShouldDelete | CanBeFake}, // 1019
- {HTTP_HEADER_TOO_LARGE, ShouldDelete}, // 1020
- {HTTP_URL_TOO_LARGE, ShouldDelete}, // 1021
- {HTTP_INTERRUPTED, 0}, // 1022
- {HTTP_CUSTOM_NOT_MODIFIED, 0}, // 1023
- {HTTP_BAD_CONTENT_ENCODING, ShouldDelete}, // 1024
- {HTTP_PROXY_UNKNOWN, 0}, // 1030
- {HTTP_PROXY_REQUEST_TIME_OUT, 0}, // 1031
- {HTTP_PROXY_INTERNAL_ERROR, 0}, // 1032
- {HTTP_PROXY_CONNECT_FAILED, 0}, // 1033
- {HTTP_PROXY_CONNECTION_LOST, 0}, // 1034
- {HTTP_PROXY_NO_PROXY, 0}, // 1035
- {HTTP_PROXY_ERROR, 0}, // 1036
- {HTTP_SSL_ERROR, 0}, // 1037
- {HTTP_CACHED_COPY_NOT_FOUND, 0}, // 1038
- {HTTP_TIMEDOUT_WHILE_BYTES_RECEIVING, ShouldRetry}, // 1039
- {HTTP_FETCHER_BAD_RESPONSE, 0}, // 1040
- {HTTP_FETCHER_MB_ERROR, 0}, // 1041
- {HTTP_SSL_CERT_ERROR, 0}, // 1042
+ // custom
+ {HTTP_BAD_RESPONSE_HEADER, CrazyServer}, // 1000
+ {HTTP_CONNECTION_LOST, ShouldRetry}, // 1001
+ {HTTP_BODY_TOO_LARGE, ShouldDelete | CanBeFake}, // 1002
+ {HTTP_ROBOTS_TXT_DISALLOW, ShouldDelete}, // 1003
+ {HTTP_BAD_URL, ShouldDelete}, // 1004
+ {HTTP_BAD_MIME, ShouldDelete}, // 1005
+ {HTTP_DNS_FAILURE, ShouldDisconnect | MarkSuspect}, // 1006
+ {HTTP_BAD_STATUS_CODE, CrazyServer}, // 1007
+ {HTTP_BAD_HEADER_STRING, CrazyServer}, // 1008
+ {HTTP_BAD_CHUNK, CrazyServer}, // 1009
+ {HTTP_CONNECT_FAILED, ShouldDisconnect | ShouldRetry | MarkSuspect}, // 1010
+ {HTTP_FILTER_DISALLOW, ShouldDelete}, // 1011
+ {HTTP_LOCAL_EIO, ShouldRetry}, // 1012
+ {HTTP_BAD_CONTENT_LENGTH, ShouldDelete}, // 1013
+ {HTTP_BAD_ENCODING, ShouldDelete}, // 1014
+ {HTTP_LENGTH_UNKNOWN, ShouldDelete}, // 1015
+ {HTTP_HEADER_EOF, ShouldRetry | CanBeFake}, // 1016
+ {HTTP_MESSAGE_EOF, ShouldRetry | CanBeFake}, // 1017
+ {HTTP_CHUNK_EOF, ShouldRetry | CanBeFake}, // 1018
+ {HTTP_PAST_EOF, ShouldRetry | ShouldDelete | CanBeFake}, // 1019
+ {HTTP_HEADER_TOO_LARGE, ShouldDelete}, // 1020
+ {HTTP_URL_TOO_LARGE, ShouldDelete}, // 1021
+ {HTTP_INTERRUPTED, 0}, // 1022
+ {HTTP_CUSTOM_NOT_MODIFIED, 0}, // 1023
+ {HTTP_BAD_CONTENT_ENCODING, ShouldDelete}, // 1024
+ {HTTP_PROXY_UNKNOWN, 0}, // 1030
+ {HTTP_PROXY_REQUEST_TIME_OUT, 0}, // 1031
+ {HTTP_PROXY_INTERNAL_ERROR, 0}, // 1032
+ {HTTP_PROXY_CONNECT_FAILED, 0}, // 1033
+ {HTTP_PROXY_CONNECTION_LOST, 0}, // 1034
+ {HTTP_PROXY_NO_PROXY, 0}, // 1035
+ {HTTP_PROXY_ERROR, 0}, // 1036
+ {HTTP_SSL_ERROR, 0}, // 1037
+ {HTTP_CACHED_COPY_NOT_FOUND, 0}, // 1038
+ {HTTP_TIMEDOUT_WHILE_BYTES_RECEIVING, ShouldRetry}, // 1039
+ {HTTP_FETCHER_BAD_RESPONSE, 0}, // 1040
+ {HTTP_FETCHER_MB_ERROR, 0}, // 1041
+ {HTTP_SSL_CERT_ERROR, 0}, // 1042
- // Custom (replace HTTP 200/304)
- {EXT_HTTP_MIRRMOVE, 0}, // 2000
- {EXT_HTTP_MANUAL_DELETE, ShouldDelete}, // 2001
- {EXT_HTTP_NOTUSED2, ShouldDelete}, // 2002
- {EXT_HTTP_NOTUSED3, ShouldDelete}, // 2003
- {EXT_HTTP_REFRESH, ShouldDelete | CheckLinks | MoveRedir}, // 2004
- {EXT_HTTP_NOINDEX, ShouldDelete | CheckLinks}, // 2005
- {EXT_HTTP_BADCODES, ShouldDelete}, // 2006
- {EXT_HTTP_SITESTAT, ShouldDelete}, // 2007
- {EXT_HTTP_IOERROR, ShouldDelete}, // 2008
- {EXT_HTTP_BASEERROR, ShouldDelete}, // 2009
- {EXT_HTTP_PARSERROR, ShouldDelete | CanBeFake}, // 2010
- {EXT_HTTP_BAD_CHARSET, ShouldDelete | CheckLinks}, // 2011
- {EXT_HTTP_BAD_LANGUAGE, ShouldDelete | CheckLinks}, // 2012
- {EXT_HTTP_NUMERERROR, ShouldDelete}, // 2013
- {EXT_HTTP_EMPTYDOC, ShouldDelete | CheckLinks}, // 2014
- {EXT_HTTP_HUGEDOC, ShouldDelete}, // 2015
- {EXT_HTTP_LINKGARBAGE, ShouldDelete}, // 2016
- {EXT_HTTP_PARSERFAIL, ShouldDelete}, // 2019
- {EXT_HTTP_GZIPERROR, ShouldDelete}, // 2020
- {EXT_HTTP_MANUAL_DELETE_URL, ShouldDelete}, // 2022
- {EXT_HTTP_CUSTOM_PARTIAL_CONTENT, ShouldReindex}, // 2023
- {EXT_HTTP_EMPTY_RESPONSE, ShouldDelete}, // 2024
- {EXT_HTTP_REL_CANONICAL, ShouldDelete | CheckLinks | MoveRedir}, // 2025
- {0, 0}};
+ // Custom (replace HTTP 200/304)
+ {EXT_HTTP_MIRRMOVE, 0}, // 2000
+ {EXT_HTTP_MANUAL_DELETE, ShouldDelete}, // 2001
+ {EXT_HTTP_NOTUSED2, ShouldDelete}, // 2002
+ {EXT_HTTP_NOTUSED3, ShouldDelete}, // 2003
+ {EXT_HTTP_REFRESH, ShouldDelete | CheckLinks | MoveRedir}, // 2004
+ {EXT_HTTP_NOINDEX, ShouldDelete | CheckLinks}, // 2005
+ {EXT_HTTP_BADCODES, ShouldDelete}, // 2006
+ {EXT_HTTP_SITESTAT, ShouldDelete}, // 2007
+ {EXT_HTTP_IOERROR, ShouldDelete}, // 2008
+ {EXT_HTTP_BASEERROR, ShouldDelete}, // 2009
+ {EXT_HTTP_PARSERROR, ShouldDelete | CanBeFake}, // 2010
+ {EXT_HTTP_BAD_CHARSET, ShouldDelete | CheckLinks}, // 2011
+ {EXT_HTTP_BAD_LANGUAGE, ShouldDelete | CheckLinks}, // 2012
+ {EXT_HTTP_NUMERERROR, ShouldDelete}, // 2013
+ {EXT_HTTP_EMPTYDOC, ShouldDelete | CheckLinks}, // 2014
+ {EXT_HTTP_HUGEDOC, ShouldDelete}, // 2015
+ {EXT_HTTP_LINKGARBAGE, ShouldDelete}, // 2016
+ {EXT_HTTP_PARSERFAIL, ShouldDelete}, // 2019
+ {EXT_HTTP_GZIPERROR, ShouldDelete}, // 2020
+ {EXT_HTTP_MANUAL_DELETE_URL, ShouldDelete}, // 2022
+ {EXT_HTTP_CUSTOM_PARTIAL_CONTENT, ShouldReindex}, // 2023
+ {EXT_HTTP_EMPTY_RESPONSE, ShouldDelete}, // 2024
+ {EXT_HTTP_REL_CANONICAL, ShouldDelete | CheckLinks | MoveRedir}, // 2025
+ {0, 0}};
-static ui16* prepare_flags(http_flag* arg) {
+static ui16* prepare_flags(http_flag* arg) {
static ui16 flags[EXT_HTTP_CODE_MAX];
- http_flag* ptr;
+ http_flag* ptr;
size_t i;
// устанавливаем значение по умолчанию для кодов не перечисленных в таблице выше
- for (i = 0; i < EXT_HTTP_CODE_MAX; ++i)
+ for (i = 0; i < EXT_HTTP_CODE_MAX; ++i)
flags[i] = CrazyServer;
// устанавливаем флаги для перечисленных кодов
- for (ptr = arg; ptr->http; ++ptr)
- flags[ptr->http & (EXT_HTTP_CODE_MAX - 1)] = ptr->flag;
+ for (ptr = arg; ptr->http; ++ptr)
+ flags[ptr->http & (EXT_HTTP_CODE_MAX - 1)] = ptr->flag;
// для стандартных кодов ошибок берем флаги из первого кода каждой группы и проставляем их
// всем кодам не перечисленным в таблице выше
@@ -164,103 +164,103 @@ static ui16* prepare_flags(http_flag* arg) {
// предыдущий цикл затер некоторые флаги перечисленные в таблице выше
// восстанавливаем их
- for (ptr = arg; ptr->http; ++ptr)
- flags[ptr->http & (EXT_HTTP_CODE_MAX - 1)] = ptr->flag;
+ for (ptr = arg; ptr->http; ++ptr)
+ flags[ptr->http & (EXT_HTTP_CODE_MAX - 1)] = ptr->flag;
return flags;
}
-ui16* http2status = prepare_flags(HTTP_FLAG);
+ui16* http2status = prepare_flags(HTTP_FLAG);
TStringBuf ExtHttpCodeStr(int code) noexcept {
if (code < HTTP_CODE_MAX) {
return HttpCodeStr(code);
}
switch (code) {
- case HTTP_BAD_RESPONSE_HEADER:
+ case HTTP_BAD_RESPONSE_HEADER:
return TStringBuf("Bad response header");
- case HTTP_CONNECTION_LOST:
+ case HTTP_CONNECTION_LOST:
return TStringBuf("Connection lost");
- case HTTP_BODY_TOO_LARGE:
+ case HTTP_BODY_TOO_LARGE:
return TStringBuf("Body too large");
- case HTTP_ROBOTS_TXT_DISALLOW:
+ case HTTP_ROBOTS_TXT_DISALLOW:
return TStringBuf("robots.txt disallow");
- case HTTP_BAD_URL:
+ case HTTP_BAD_URL:
return TStringBuf("Bad url");
- case HTTP_BAD_MIME:
+ case HTTP_BAD_MIME:
return TStringBuf("Bad mime type");
- case HTTP_DNS_FAILURE:
+ case HTTP_DNS_FAILURE:
return TStringBuf("Dns failure");
- case HTTP_BAD_STATUS_CODE:
+ case HTTP_BAD_STATUS_CODE:
return TStringBuf("Bad status code");
- case HTTP_BAD_HEADER_STRING:
+ case HTTP_BAD_HEADER_STRING:
return TStringBuf("Bad header string");
- case HTTP_BAD_CHUNK:
+ case HTTP_BAD_CHUNK:
return TStringBuf("Bad chunk");
- case HTTP_CONNECT_FAILED:
+ case HTTP_CONNECT_FAILED:
return TStringBuf("Connect failed");
- case HTTP_FILTER_DISALLOW:
+ case HTTP_FILTER_DISALLOW:
return TStringBuf("Filter disallow");
- case HTTP_LOCAL_EIO:
+ case HTTP_LOCAL_EIO:
return TStringBuf("Local eio");
- case HTTP_BAD_CONTENT_LENGTH:
+ case HTTP_BAD_CONTENT_LENGTH:
return TStringBuf("Bad content length");
- case HTTP_BAD_ENCODING:
+ case HTTP_BAD_ENCODING:
return TStringBuf("Bad encoding");
- case HTTP_LENGTH_UNKNOWN:
+ case HTTP_LENGTH_UNKNOWN:
return TStringBuf("Length unknown");
- case HTTP_HEADER_EOF:
+ case HTTP_HEADER_EOF:
return TStringBuf("Header EOF");
- case HTTP_MESSAGE_EOF:
+ case HTTP_MESSAGE_EOF:
return TStringBuf("Message EOF");
- case HTTP_CHUNK_EOF:
+ case HTTP_CHUNK_EOF:
return TStringBuf("Chunk EOF");
- case HTTP_PAST_EOF:
+ case HTTP_PAST_EOF:
return TStringBuf("Past EOF");
- case HTTP_HEADER_TOO_LARGE:
+ case HTTP_HEADER_TOO_LARGE:
return TStringBuf("Header is too large");
- case HTTP_URL_TOO_LARGE:
+ case HTTP_URL_TOO_LARGE:
return TStringBuf("Url is too large");
- case HTTP_INTERRUPTED:
+ case HTTP_INTERRUPTED:
return TStringBuf("Interrupted");
- case HTTP_CUSTOM_NOT_MODIFIED:
+ case HTTP_CUSTOM_NOT_MODIFIED:
return TStringBuf("Signature detector thinks that doc is not modified");
- case HTTP_BAD_CONTENT_ENCODING:
+ case HTTP_BAD_CONTENT_ENCODING:
return TStringBuf("Bad content encoding");
- case HTTP_NO_RESOURCES:
+ case HTTP_NO_RESOURCES:
return TStringBuf("No resources");
- case HTTP_FETCHER_SHUTDOWN:
+ case HTTP_FETCHER_SHUTDOWN:
return TStringBuf("Fetcher shutdown");
- case HTTP_CHUNK_TOO_LARGE:
+ case HTTP_CHUNK_TOO_LARGE:
return TStringBuf("Chunk size is too big");
- case HTTP_SERVER_BUSY:
+ case HTTP_SERVER_BUSY:
return TStringBuf("Server is busy");
- case HTTP_SERVICE_UNKNOWN:
+ case HTTP_SERVICE_UNKNOWN:
return TStringBuf("Service is unknown");
- case HTTP_PROXY_UNKNOWN:
+ case HTTP_PROXY_UNKNOWN:
return TStringBuf("Zora: unknown error");
- case HTTP_PROXY_REQUEST_TIME_OUT:
+ case HTTP_PROXY_REQUEST_TIME_OUT:
return TStringBuf("Zora: request time out");
- case HTTP_PROXY_INTERNAL_ERROR:
+ case HTTP_PROXY_INTERNAL_ERROR:
return TStringBuf("Zora: internal server error");
- case HTTP_PROXY_CONNECT_FAILED:
+ case HTTP_PROXY_CONNECT_FAILED:
return TStringBuf("Spider proxy connect failed");
- case HTTP_PROXY_CONNECTION_LOST:
+ case HTTP_PROXY_CONNECTION_LOST:
return TStringBuf("Spider proxy connection lost");
- case HTTP_PROXY_NO_PROXY:
+ case HTTP_PROXY_NO_PROXY:
return TStringBuf("Spider proxy no proxy alive in region");
- case HTTP_PROXY_ERROR:
+ case HTTP_PROXY_ERROR:
return TStringBuf("Spider proxy returned custom error");
- case HTTP_SSL_ERROR:
+ case HTTP_SSL_ERROR:
return TStringBuf("Ssl library returned error");
- case HTTP_CACHED_COPY_NOT_FOUND:
+ case HTTP_CACHED_COPY_NOT_FOUND:
return TStringBuf("Cached copy for the url is not available");
- case HTTP_TIMEDOUT_WHILE_BYTES_RECEIVING:
+ case HTTP_TIMEDOUT_WHILE_BYTES_RECEIVING:
return TStringBuf("Timed out while bytes receiving");
- // TODO: messages for >2000 codes
+ // TODO: messages for >2000 codes
- default:
+ default:
return TStringBuf("Unknown HTTP code");
}
}
diff --git a/library/cpp/http/fetch/exthttpcodes.h b/library/cpp/http/fetch/exthttpcodes.h
index 537e4ac6df..6b525052cd 100644
--- a/library/cpp/http/fetch/exthttpcodes.h
+++ b/library/cpp/http/fetch/exthttpcodes.h
@@ -5,110 +5,110 @@
enum ExtHttpCodes {
// Custom
- HTTP_EXTENDED = 1000,
- HTTP_BAD_RESPONSE_HEADER = 1000,
- HTTP_CONNECTION_LOST = 1001,
- HTTP_BODY_TOO_LARGE = 1002,
- HTTP_ROBOTS_TXT_DISALLOW = 1003,
- HTTP_BAD_URL = 1004,
- HTTP_BAD_MIME = 1005,
- HTTP_DNS_FAILURE = 1006,
- HTTP_BAD_STATUS_CODE = 1007,
- HTTP_BAD_HEADER_STRING = 1008,
- HTTP_BAD_CHUNK = 1009,
- HTTP_CONNECT_FAILED = 1010,
- HTTP_FILTER_DISALLOW = 1011,
- HTTP_LOCAL_EIO = 1012,
- HTTP_BAD_CONTENT_LENGTH = 1013,
- HTTP_BAD_ENCODING = 1014,
- HTTP_LENGTH_UNKNOWN = 1015,
- HTTP_HEADER_EOF = 1016,
- HTTP_MESSAGE_EOF = 1017,
- HTTP_CHUNK_EOF = 1018,
- HTTP_PAST_EOF = 1019,
- HTTP_HEADER_TOO_LARGE = 1020,
- HTTP_URL_TOO_LARGE = 1021,
- HTTP_INTERRUPTED = 1022,
- HTTP_CUSTOM_NOT_MODIFIED = 1023,
- HTTP_BAD_CONTENT_ENCODING = 1024,
- HTTP_NO_RESOURCES = 1025,
- HTTP_FETCHER_SHUTDOWN = 1026,
- HTTP_CHUNK_TOO_LARGE = 1027,
- HTTP_SERVER_BUSY = 1028,
- HTTP_SERVICE_UNKNOWN = 1029,
- HTTP_PROXY_UNKNOWN = 1030,
- HTTP_PROXY_REQUEST_TIME_OUT = 1031,
- HTTP_PROXY_INTERNAL_ERROR = 1032,
- HTTP_PROXY_CONNECT_FAILED = 1033,
- HTTP_PROXY_CONNECTION_LOST = 1034,
- HTTP_PROXY_NO_PROXY = 1035,
- HTTP_PROXY_ERROR = 1036,
- HTTP_SSL_ERROR = 1037,
- HTTP_CACHED_COPY_NOT_FOUND = 1038,
+ HTTP_EXTENDED = 1000,
+ HTTP_BAD_RESPONSE_HEADER = 1000,
+ HTTP_CONNECTION_LOST = 1001,
+ HTTP_BODY_TOO_LARGE = 1002,
+ HTTP_ROBOTS_TXT_DISALLOW = 1003,
+ HTTP_BAD_URL = 1004,
+ HTTP_BAD_MIME = 1005,
+ HTTP_DNS_FAILURE = 1006,
+ HTTP_BAD_STATUS_CODE = 1007,
+ HTTP_BAD_HEADER_STRING = 1008,
+ HTTP_BAD_CHUNK = 1009,
+ HTTP_CONNECT_FAILED = 1010,
+ HTTP_FILTER_DISALLOW = 1011,
+ HTTP_LOCAL_EIO = 1012,
+ HTTP_BAD_CONTENT_LENGTH = 1013,
+ HTTP_BAD_ENCODING = 1014,
+ HTTP_LENGTH_UNKNOWN = 1015,
+ HTTP_HEADER_EOF = 1016,
+ HTTP_MESSAGE_EOF = 1017,
+ HTTP_CHUNK_EOF = 1018,
+ HTTP_PAST_EOF = 1019,
+ HTTP_HEADER_TOO_LARGE = 1020,
+ HTTP_URL_TOO_LARGE = 1021,
+ HTTP_INTERRUPTED = 1022,
+ HTTP_CUSTOM_NOT_MODIFIED = 1023,
+ HTTP_BAD_CONTENT_ENCODING = 1024,
+ HTTP_NO_RESOURCES = 1025,
+ HTTP_FETCHER_SHUTDOWN = 1026,
+ HTTP_CHUNK_TOO_LARGE = 1027,
+ HTTP_SERVER_BUSY = 1028,
+ HTTP_SERVICE_UNKNOWN = 1029,
+ HTTP_PROXY_UNKNOWN = 1030,
+ HTTP_PROXY_REQUEST_TIME_OUT = 1031,
+ HTTP_PROXY_INTERNAL_ERROR = 1032,
+ HTTP_PROXY_CONNECT_FAILED = 1033,
+ HTTP_PROXY_CONNECTION_LOST = 1034,
+ HTTP_PROXY_NO_PROXY = 1035,
+ HTTP_PROXY_ERROR = 1036,
+ HTTP_SSL_ERROR = 1037,
+ HTTP_CACHED_COPY_NOT_FOUND = 1038,
HTTP_TIMEDOUT_WHILE_BYTES_RECEIVING = 1039,
- HTTP_FETCHER_BAD_RESPONSE = 1040,
- HTTP_FETCHER_MB_ERROR = 1041,
- HTTP_SSL_CERT_ERROR = 1042,
- HTTP_PROXY_REQUEST_CANCELED = 1051,
+ HTTP_FETCHER_BAD_RESPONSE = 1040,
+ HTTP_FETCHER_MB_ERROR = 1041,
+ HTTP_SSL_CERT_ERROR = 1042,
+ HTTP_PROXY_REQUEST_CANCELED = 1051,
// Custom (replace HTTP 200/304)
- EXT_HTTP_EXT_SUCCESS_BEGIN = 2000, // to check if code variable is in success interval
- EXT_HTTP_MIRRMOVE = 2000,
- EXT_HTTP_MANUAL_DELETE = 2001,
- EXT_HTTP_NOTUSED2 = 2002,
- EXT_HTTP_NOTUSED3 = 2003,
- EXT_HTTP_REFRESH = 2004,
- EXT_HTTP_NOINDEX = 2005,
- EXT_HTTP_BADCODES = 2006,
- EXT_HTTP_SITESTAT = 2007,
- EXT_HTTP_IOERROR = 2008,
- EXT_HTTP_BASEERROR = 2009,
- EXT_HTTP_PARSERROR = 2010,
- EXT_HTTP_BAD_CHARSET = 2011,
- EXT_HTTP_BAD_LANGUAGE = 2012,
- EXT_HTTP_NUMERERROR = 2013,
- EXT_HTTP_EMPTYDOC = 2014,
- EXT_HTTP_HUGEDOC = 2015,
- EXT_HTTP_LINKGARBAGE = 2016,
- EXT_HTTP_EXDUPLICATE = 2017,
- EXT_HTTP_FILTERED = 2018,
- EXT_HTTP_PARSERFAIL = 2019, // parser crashed (in this case image spider will redownload such document)
- EXT_HTTP_GZIPERROR = 2020,
- EXT_HTTP_CLEANPARAM = 2021,
- EXT_HTTP_MANUAL_DELETE_URL = 2022,
- EXT_HTTP_CUSTOM_PARTIAL_CONTENT = 2023,
- EXT_HTTP_EMPTY_RESPONSE = 2024,
- EXT_HTTP_REL_CANONICAL = 2025,
+ EXT_HTTP_EXT_SUCCESS_BEGIN = 2000, // to check if code variable is in success interval
+ EXT_HTTP_MIRRMOVE = 2000,
+ EXT_HTTP_MANUAL_DELETE = 2001,
+ EXT_HTTP_NOTUSED2 = 2002,
+ EXT_HTTP_NOTUSED3 = 2003,
+ EXT_HTTP_REFRESH = 2004,
+ EXT_HTTP_NOINDEX = 2005,
+ EXT_HTTP_BADCODES = 2006,
+ EXT_HTTP_SITESTAT = 2007,
+ EXT_HTTP_IOERROR = 2008,
+ EXT_HTTP_BASEERROR = 2009,
+ EXT_HTTP_PARSERROR = 2010,
+ EXT_HTTP_BAD_CHARSET = 2011,
+ EXT_HTTP_BAD_LANGUAGE = 2012,
+ EXT_HTTP_NUMERERROR = 2013,
+ EXT_HTTP_EMPTYDOC = 2014,
+ EXT_HTTP_HUGEDOC = 2015,
+ EXT_HTTP_LINKGARBAGE = 2016,
+ EXT_HTTP_EXDUPLICATE = 2017,
+ EXT_HTTP_FILTERED = 2018,
+ EXT_HTTP_PARSERFAIL = 2019, // parser crashed (in this case image spider will redownload such document)
+ EXT_HTTP_GZIPERROR = 2020,
+ EXT_HTTP_CLEANPARAM = 2021,
+ EXT_HTTP_MANUAL_DELETE_URL = 2022,
+ EXT_HTTP_CUSTOM_PARTIAL_CONTENT = 2023,
+ EXT_HTTP_EMPTY_RESPONSE = 2024,
+ EXT_HTTP_REL_CANONICAL = 2025,
- EXT_HTTP_EXT_SUCCESS_END = 3000, // to check if code variable is in success interval
- EXT_HTTP_HOSTFILTER = 3001,
- EXT_HTTP_URLFILTER = 3002,
- EXT_HTTP_SUFFIXFILTER = 3003,
- EXT_HTTP_DOMAINFILTER = 3004,
- EXT_HTTP_EXTDOMAINFILTER = 3005,
- EXT_HTTP_PORTFILTER = 3006,
- EXT_HTTP_MIRROR = 3007,
- EXT_HTTP_DEEPDIR = 3008,
- EXT_HTTP_DUPDIRS = 3009,
- EXT_HTTP_REGEXP = 3010,
- EXT_HTTP_OLDDELETED = 3012,
- EXT_HTTP_PENALTY = 3013,
- EXT_HTTP_POLICY = 3015,
- EXT_HTTP_TOOOLD = 3016,
- EXT_HTTP_GARBAGE = 3017,
- EXT_HTTP_FOREIGN = 3018,
- EXT_HTTP_EXT_REGEXP = 3019,
- EXT_HTTP_HOPS = 3020,
- EXT_HTTP_SELRANK = 3021,
- EXT_HTTP_NOLINKS = 3022,
- EXT_HTTP_WRONGMULTILANG = 3023,
- EXT_HTTP_SOFTMIRRORS = 3024,
- EXT_HTTP_BIGLEVEL = 3025,
+ EXT_HTTP_EXT_SUCCESS_END = 3000, // to check if code variable is in success interval
+ EXT_HTTP_HOSTFILTER = 3001,
+ EXT_HTTP_URLFILTER = 3002,
+ EXT_HTTP_SUFFIXFILTER = 3003,
+ EXT_HTTP_DOMAINFILTER = 3004,
+ EXT_HTTP_EXTDOMAINFILTER = 3005,
+ EXT_HTTP_PORTFILTER = 3006,
+ EXT_HTTP_MIRROR = 3007,
+ EXT_HTTP_DEEPDIR = 3008,
+ EXT_HTTP_DUPDIRS = 3009,
+ EXT_HTTP_REGEXP = 3010,
+ EXT_HTTP_OLDDELETED = 3012,
+ EXT_HTTP_PENALTY = 3013,
+ EXT_HTTP_POLICY = 3015,
+ EXT_HTTP_TOOOLD = 3016,
+ EXT_HTTP_GARBAGE = 3017,
+ EXT_HTTP_FOREIGN = 3018,
+ EXT_HTTP_EXT_REGEXP = 3019,
+ EXT_HTTP_HOPS = 3020,
+ EXT_HTTP_SELRANK = 3021,
+ EXT_HTTP_NOLINKS = 3022,
+ EXT_HTTP_WRONGMULTILANG = 3023,
+ EXT_HTTP_SOFTMIRRORS = 3024,
+ EXT_HTTP_BIGLEVEL = 3025,
// fast robot codes
- EXT_HTTP_FASTHOPS = 4000,
- EXT_HTTP_NODOC = 4001,
+ EXT_HTTP_FASTHOPS = 4000,
+ EXT_HTTP_NODOC = 4001,
EXT_HTTP_MAX
};
@@ -116,26 +116,26 @@ enum ExtHttpCodes {
enum HttpFlags {
// connection
ShouldDisconnect = 1,
- ShouldRetry = 2,
+ ShouldRetry = 2,
// UNUSED 4
// indexer
- ShouldReindex = 8,
- ShouldDelete = 16,
- CheckLocation = 32,
- CheckLinks = 64,
- MarkSuspect = 128,
+ ShouldReindex = 8,
+ ShouldDelete = 16,
+ CheckLocation = 32,
+ CheckLinks = 64,
+ MarkSuspect = 128,
// UNUSED 256
// UNUSED 512
- MoveRedir = 1024,
- CanBeFake = 2048,
+ MoveRedir = 1024,
+ CanBeFake = 2048,
};
const size_t EXT_HTTP_CODE_MAX = 1 << 12;
static inline int Http2Status(int code) {
- extern ui16* http2status;
- return http2status[code & (EXT_HTTP_CODE_MAX - 1)];
+ extern ui16* http2status;
+ return http2status[code & (EXT_HTTP_CODE_MAX - 1)];
}
TStringBuf ExtHttpCodeStr(int code) noexcept;
diff --git a/library/cpp/http/fetch/http_digest.cpp b/library/cpp/http/fetch/http_digest.cpp
index 79c5a25319..1eaa02b7f2 100644
--- a/library/cpp/http/fetch/http_digest.cpp
+++ b/library/cpp/http/fetch/http_digest.cpp
@@ -1,5 +1,5 @@
-#include "http_digest.h"
-
+#include "http_digest.h"
+
#include <library/cpp/digest/md5/md5.h>
#include <util/stream/output.h>
#include <util/stream/str.h>
@@ -9,76 +9,76 @@
static const char* WWW_PREFIX = "Authorization: Digest ";
/************************************************************/
-httpDigestHandler::httpDigestHandler()
- : User_(nullptr)
- , Password_(nullptr)
- , Nonce_(nullptr)
- , NonceCount_(0)
- , HeaderInstruction_(nullptr)
+httpDigestHandler::httpDigestHandler()
+ : User_(nullptr)
+ , Password_(nullptr)
+ , Nonce_(nullptr)
+ , NonceCount_(0)
+ , HeaderInstruction_(nullptr)
{
}
/************************************************************/
-httpDigestHandler::~httpDigestHandler() {
+httpDigestHandler::~httpDigestHandler() {
clear();
}
/************************************************************/
-void httpDigestHandler::clear() {
- free(Nonce_);
- free(HeaderInstruction_);
+void httpDigestHandler::clear() {
+ free(Nonce_);
+ free(HeaderInstruction_);
User_ = Password_ = nullptr;
Nonce_ = HeaderInstruction_ = nullptr;
- NonceCount_ = 0;
+ NonceCount_ = 0;
}
/************************************************************/
-void httpDigestHandler::setAuthorization(const char* user, const char* password) {
+void httpDigestHandler::setAuthorization(const char* user, const char* password) {
clear();
- if (user && password) {
- User_ = user;
- Password_ = password;
+ if (user && password) {
+ User_ = user;
+ Password_ = password;
}
}
/************************************************************/
-const char* httpDigestHandler::getHeaderInstruction() const {
- return HeaderInstruction_;
+const char* httpDigestHandler::getHeaderInstruction() const {
+ return HeaderInstruction_;
}
/************************************************************/
-void httpDigestHandler::generateCNonce(char* outCNonce) {
+void httpDigestHandler::generateCNonce(char* outCNonce) {
if (!*outCNonce)
sprintf(outCNonce, "%ld", (long)time(nullptr));
}
/************************************************************/
-inline void addMD5(MD5& ctx, const char* value) {
+inline void addMD5(MD5& ctx, const char* value) {
ctx.Update((const unsigned char*)(value), strlen(value));
}
-inline void addMD5(MD5& ctx, const char* value, int len) {
+inline void addMD5(MD5& ctx, const char* value, int len) {
ctx.Update((const unsigned char*)(value), len);
}
-inline void addMD5Sep(MD5& ctx) {
+inline void addMD5Sep(MD5& ctx) {
addMD5(ctx, ":", 1);
}
/************************************************************/
/* calculate H(A1) as per spec */
-void httpDigestHandler::digestCalcHA1(const THttpAuthHeader& hd,
- char* outSessionKey,
- char* outCNonce) {
+void httpDigestHandler::digestCalcHA1(const THttpAuthHeader& hd,
+ char* outSessionKey,
+ char* outCNonce) {
MD5 ctx;
ctx.Init();
- addMD5(ctx, User_);
- addMD5Sep(ctx);
- addMD5(ctx, hd.realm);
- addMD5Sep(ctx);
- addMD5(ctx, Password_);
+ addMD5(ctx, User_);
+ addMD5Sep(ctx);
+ addMD5(ctx, hd.realm);
+ addMD5Sep(ctx);
+ addMD5(ctx, Password_);
- if (hd.algorithm == 1) { //MD5-sess
+ if (hd.algorithm == 1) { //MD5-sess
unsigned char digest[16];
ctx.Final(digest);
@@ -86,91 +86,91 @@ void httpDigestHandler::digestCalcHA1(const THttpAuthHeader& hd,
ctx.Init();
ctx.Update(digest, 16);
- addMD5Sep(ctx);
- addMD5(ctx, hd.nonce);
- addMD5Sep(ctx);
- addMD5(ctx, outCNonce);
+ addMD5Sep(ctx);
+ addMD5(ctx, hd.nonce);
+ addMD5Sep(ctx);
+ addMD5(ctx, outCNonce);
ctx.End(outSessionKey);
}
- ctx.End(outSessionKey);
+ ctx.End(outSessionKey);
};
/************************************************************/
/* calculate request-digest/response-digest as per HTTP Digest spec */
-void httpDigestHandler::digestCalcResponse(const THttpAuthHeader& hd,
- const char* path,
- const char* method,
- const char* nonceCount,
- char* outResponse,
- char* outCNonce) {
+void httpDigestHandler::digestCalcResponse(const THttpAuthHeader& hd,
+ const char* path,
+ const char* method,
+ const char* nonceCount,
+ char* outResponse,
+ char* outCNonce) {
char HA1[33];
digestCalcHA1(hd, HA1, outCNonce);
char HA2[33];
MD5 ctx;
ctx.Init();
- addMD5(ctx, method);
- addMD5Sep(ctx);
- addMD5(ctx, path);
+ addMD5(ctx, method);
+ addMD5Sep(ctx);
+ addMD5(ctx, path);
//ignore auth-int
ctx.End(HA2);
ctx.Init();
- addMD5(ctx, HA1, 32);
- addMD5Sep(ctx);
- addMD5(ctx, Nonce_);
- addMD5Sep(ctx);
+ addMD5(ctx, HA1, 32);
+ addMD5Sep(ctx);
+ addMD5(ctx, Nonce_);
+ addMD5Sep(ctx);
- if (hd.qop_auth) {
+ if (hd.qop_auth) {
if (!*outCNonce)
generateCNonce(outCNonce);
- addMD5(ctx, nonceCount, 8);
- addMD5Sep(ctx);
- addMD5(ctx, outCNonce);
- addMD5Sep(ctx);
- addMD5(ctx, "auth", 4);
- addMD5Sep(ctx);
+ addMD5(ctx, nonceCount, 8);
+ addMD5Sep(ctx);
+ addMD5(ctx, outCNonce);
+ addMD5Sep(ctx);
+ addMD5(ctx, "auth", 4);
+ addMD5Sep(ctx);
}
- addMD5(ctx, HA2, 32);
+ addMD5(ctx, HA2, 32);
ctx.End(outResponse);
}
/************************************************************/
-bool httpDigestHandler::processHeader(const THttpAuthHeader* header,
- const char* path,
- const char* method,
- const char* cnonce) {
- if (!User_ || !header || !header->use_auth || !header->realm || !header->nonce)
+bool httpDigestHandler::processHeader(const THttpAuthHeader* header,
+ const char* path,
+ const char* method,
+ const char* cnonce) {
+ if (!User_ || !header || !header->use_auth || !header->realm || !header->nonce)
return false;
- if (Nonce_) {
- if (strcmp(Nonce_, header->nonce)) {
- free(Nonce_);
+ if (Nonce_) {
+ if (strcmp(Nonce_, header->nonce)) {
+ free(Nonce_);
Nonce_ = nullptr;
- NonceCount_ = 0;
+ NonceCount_ = 0;
}
}
- if (!Nonce_) {
- Nonce_ = strdup(header->nonce);
- NonceCount_ = 0;
+ if (!Nonce_) {
+ Nonce_ = strdup(header->nonce);
+ NonceCount_ = 0;
}
- free(HeaderInstruction_);
+ free(HeaderInstruction_);
HeaderInstruction_ = nullptr;
- NonceCount_++;
+ NonceCount_++;
char nonceCount[20];
- sprintf(nonceCount, "%08d", NonceCount_);
+ sprintf(nonceCount, "%08d", NonceCount_);
char CNonce[50];
if (cnonce)
strcpy(CNonce, cnonce);
else
- CNonce[0] = 0;
+ CNonce[0] = 0;
char response[33];
- digestCalcResponse(*header, path, method, nonceCount, response, CNonce);
+ digestCalcResponse(*header, path, method, nonceCount, response, CNonce);
//digest-response = 1#( username | realm | nonce | digest-uri
// | response | [ algorithm ] | [cnonce] |
@@ -178,11 +178,11 @@ bool httpDigestHandler::processHeader(const THttpAuthHeader* header,
// [nonce-count] | [auth-param] )
TStringStream out;
- out << WWW_PREFIX << "username=\"" << User_ << "\"";
+ out << WWW_PREFIX << "username=\"" << User_ << "\"";
out << ", realm=\"" << header->realm << "\"";
out << ", nonce=\"" << header->nonce << "\"";
out << ", uri=\"" << path << "\"";
- if (header->algorithm == 1)
+ if (header->algorithm == 1)
out << ", algorithm=MD5-sess";
else
out << ", algorithm=MD5";
@@ -197,7 +197,7 @@ bool httpDigestHandler::processHeader(const THttpAuthHeader* header,
out << "\r\n";
TString s_out = out.Str();
- HeaderInstruction_ = strdup(s_out.c_str());
+ HeaderInstruction_ = strdup(s_out.c_str());
return true;
}
diff --git a/library/cpp/http/fetch/http_digest.h b/library/cpp/http/fetch/http_digest.h
index 958737a6ac..3b1872d70b 100644
--- a/library/cpp/http/fetch/http_digest.h
+++ b/library/cpp/http/fetch/http_digest.h
@@ -1,46 +1,46 @@
#pragma once
-#include "httpheader.h"
-
+#include "httpheader.h"
+
#include <util/system/compat.h>
#include <library/cpp/http/misc/httpcodes.h>
-class httpDigestHandler {
-protected:
- const char* User_;
- const char* Password_;
- char* Nonce_;
- int NonceCount_;
- char* HeaderInstruction_;
+class httpDigestHandler {
+protected:
+ const char* User_;
+ const char* Password_;
+ char* Nonce_;
+ int NonceCount_;
+ char* HeaderInstruction_;
void clear();
- void generateCNonce(char* outCNonce);
+ void generateCNonce(char* outCNonce);
- void digestCalcHA1(const THttpAuthHeader& hd,
- char* outSessionKey,
- char* outCNonce);
+ void digestCalcHA1(const THttpAuthHeader& hd,
+ char* outSessionKey,
+ char* outCNonce);
- void digestCalcResponse(const THttpAuthHeader& hd,
- const char* method,
- const char* path,
- const char* nonceCount,
- char* outResponse,
- char* outCNonce);
+ void digestCalcResponse(const THttpAuthHeader& hd,
+ const char* method,
+ const char* path,
+ const char* nonceCount,
+ char* outResponse,
+ char* outCNonce);
-public:
+public:
httpDigestHandler();
~httpDigestHandler();
- void setAuthorization(const char* user,
- const char* password);
- bool processHeader(const THttpAuthHeader* header,
- const char* path,
- const char* method,
- const char* cnonce = nullptr);
+ void setAuthorization(const char* user,
+ const char* password);
+ bool processHeader(const THttpAuthHeader* header,
+ const char* path,
+ const char* method,
+ const char* cnonce = nullptr);
- bool empty() const {
- return (!User_);
+ bool empty() const {
+ return (!User_);
}
const char* getHeaderInstruction() const;
diff --git a/library/cpp/http/fetch/http_socket.cpp b/library/cpp/http/fetch/http_socket.cpp
index 7a5b29668c..1524ef04a8 100644
--- a/library/cpp/http/fetch/http_socket.cpp
+++ b/library/cpp/http/fetch/http_socket.cpp
@@ -7,7 +7,7 @@
#include <gcrypt.h>
#include <gnutls/gnutls.h>
-#include <util/network/init.h>
+#include <util/network/init.h>
#include <util/network/socket.h>
#include <util/system/mutex.h>
@@ -15,75 +15,75 @@
// HTTPS handler is used as implementation of
// socketAbstractHandler for work through HTTPS protocol
-class socketSecureHandler: public socketRegularHandler {
-protected:
- bool IsValid_;
- gnutls_session Session_;
- gnutls_certificate_credentials Credits_;
-
-public:
- socketSecureHandler();
- virtual ~socketSecureHandler();
-
- virtual bool Good();
- virtual int Connect(const TAddrList& addrs, TDuration Timeout);
- virtual void Disconnect();
- virtual void shutdown();
- virtual bool send(const char* message, ssize_t messlen);
- virtual bool peek();
- virtual ssize_t read(void* buffer, ssize_t buflen);
+class socketSecureHandler: public socketRegularHandler {
+protected:
+ bool IsValid_;
+ gnutls_session Session_;
+ gnutls_certificate_credentials Credits_;
+
+public:
+ socketSecureHandler();
+ virtual ~socketSecureHandler();
+
+ virtual bool Good();
+ virtual int Connect(const TAddrList& addrs, TDuration Timeout);
+ virtual void Disconnect();
+ virtual void shutdown();
+ virtual bool send(const char* message, ssize_t messlen);
+ virtual bool peek();
+ virtual ssize_t read(void* buffer, ssize_t buflen);
};
/********************************************************/
/********************************************************/
-static int gcry_pthread_mutex_init(void** priv) {
+static int gcry_pthread_mutex_init(void** priv) {
int err = 0;
try {
TMutex* lock = new TMutex;
*priv = lock;
- } catch (...) {
+ } catch (...) {
err = -1;
}
return err;
}
-static int gcry_pthread_mutex_destroy(void** lock) {
+static int gcry_pthread_mutex_destroy(void** lock) {
delete static_cast<TMutex*>(*lock);
-
+
return 0;
}
-static int gcry_pthread_mutex_lock(void** lock) {
+static int gcry_pthread_mutex_lock(void** lock) {
static_cast<TMutex*>(*lock)->Acquire();
return 0;
}
-static int gcry_pthread_mutex_unlock(void** lock) {
+static int gcry_pthread_mutex_unlock(void** lock) {
static_cast<TMutex*>(*lock)->Release();
return 0;
}
static struct gcry_thread_cbs gcry_threads_pthread =
- {
- GCRY_THREAD_OPTION_PTHREAD, NULL,
- gcry_pthread_mutex_init, gcry_pthread_mutex_destroy,
- gcry_pthread_mutex_lock, gcry_pthread_mutex_unlock,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL};
+ {
+ GCRY_THREAD_OPTION_PTHREAD, NULL,
+ gcry_pthread_mutex_init, gcry_pthread_mutex_destroy,
+ gcry_pthread_mutex_lock, gcry_pthread_mutex_unlock,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL};
/********************************************************/
-struct https_initor {
- https_initor() {
- gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
+struct https_initor {
+ https_initor() {
+ gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
gnutls_global_init();
- InitNetworkSubSystem();
+ InitNetworkSubSystem();
}
- ~https_initor() {
+ ~https_initor() {
gnutls_global_deinit();
}
};
@@ -91,112 +91,112 @@ struct https_initor {
static https_initor _initor;
/********************************************************/
-socketSecureHandler::socketSecureHandler()
- : socketRegularHandler()
- , IsValid_(false)
- , Session_()
- , Credits_()
+socketSecureHandler::socketSecureHandler()
+ : socketRegularHandler()
+ , IsValid_(false)
+ , Session_()
+ , Credits_()
{
}
/********************************************************/
-socketSecureHandler::~socketSecureHandler() {
- if (IsValid_)
+socketSecureHandler::~socketSecureHandler() {
+ if (IsValid_)
Disconnect();
}
/********************************************************/
-bool socketSecureHandler::Good() {
- return Socket_.Good() && IsValid_;
+bool socketSecureHandler::Good() {
+ return Socket_.Good() && IsValid_;
}
/********************************************************/
-int socketSecureHandler::Connect(const TAddrList& addrs, TDuration Timeout) {
- IsValid_ = false;
+int socketSecureHandler::Connect(const TAddrList& addrs, TDuration Timeout) {
+ IsValid_ = false;
int ret = socketRegularHandler::Connect(addrs, Timeout);
if (ret)
return ret;
- gnutls_certificate_allocate_credentials(&Credits_);
- gnutls_init(&Session_, GNUTLS_CLIENT);
- gnutls_set_default_priority(Session_);
- gnutls_credentials_set(Session_, GNUTLS_CRD_CERTIFICATE, Credits_);
+ gnutls_certificate_allocate_credentials(&Credits_);
+ gnutls_init(&Session_, GNUTLS_CLIENT);
+ gnutls_set_default_priority(Session_);
+ gnutls_credentials_set(Session_, GNUTLS_CRD_CERTIFICATE, Credits_);
- SOCKET fd = Socket_;
- gnutls_transport_set_ptr(Session_, (gnutls_transport_ptr)fd);
+ SOCKET fd = Socket_;
+ gnutls_transport_set_ptr(Session_, (gnutls_transport_ptr)fd);
- ret = gnutls_handshake(Session_);
+ ret = gnutls_handshake(Session_);
- if (ret < 0) {
+ if (ret < 0) {
fprintf(stderr, "*** Handshake failed\n");
gnutls_perror(ret);
- gnutls_deinit(Session_);
- if (Credits_) {
- gnutls_certificate_free_credentials(Credits_);
- Credits_ = 0;
+ gnutls_deinit(Session_);
+ if (Credits_) {
+ gnutls_certificate_free_credentials(Credits_);
+ Credits_ = 0;
}
return 1;
}
- IsValid_ = true;
- return !IsValid_;
+ IsValid_ = true;
+ return !IsValid_;
}
/********************************************************/
-void socketSecureHandler::Disconnect() {
- if (IsValid_) {
- gnutls_bye(Session_, GNUTLS_SHUT_RDWR);
- IsValid_ = false;
- gnutls_deinit(Session_);
+void socketSecureHandler::Disconnect() {
+ if (IsValid_) {
+ gnutls_bye(Session_, GNUTLS_SHUT_RDWR);
+ IsValid_ = false;
+ gnutls_deinit(Session_);
}
- if (Credits_) {
- gnutls_certificate_free_credentials(Credits_);
- Credits_ = 0;
+ if (Credits_) {
+ gnutls_certificate_free_credentials(Credits_);
+ Credits_ = 0;
}
socketRegularHandler::Disconnect();
}
/********************************************************/
-void socketSecureHandler::shutdown() {
+void socketSecureHandler::shutdown() {
}
/********************************************************/
-bool socketSecureHandler::send(const char* message, ssize_t messlen) {
- if (!IsValid_)
+bool socketSecureHandler::send(const char* message, ssize_t messlen) {
+ if (!IsValid_)
return false;
- ssize_t rv = gnutls_record_send(Session_, message, messlen);
+ ssize_t rv = gnutls_record_send(Session_, message, messlen);
return rv >= 0;
}
/********************************************************/
-bool socketSecureHandler::peek() {
+bool socketSecureHandler::peek() {
//ssize_t rv = gnutls_record_check_pending(mSession);
//return rv>0;
return true;
}
/********************************************************/
-ssize_t socketSecureHandler::read(void* buffer, ssize_t buflen) {
- if (!IsValid_)
+ssize_t socketSecureHandler::read(void* buffer, ssize_t buflen) {
+ if (!IsValid_)
return false;
- return gnutls_record_recv(Session_, (char*)buffer, buflen);
+ return gnutls_record_recv(Session_, (char*)buffer, buflen);
}
#endif
/************************************************************/
-socketAbstractHandler* socketHandlerFactory::chooseHandler(const THttpURL& url) {
- if (url.IsValidGlobal() && url.GetScheme() == THttpURL::SchemeHTTP)
+socketAbstractHandler* socketHandlerFactory::chooseHandler(const THttpURL& url) {
+ if (url.IsValidGlobal() && url.GetScheme() == THttpURL::SchemeHTTP)
return new socketRegularHandler;
-#ifdef USE_GNUTLS
- if (url.IsValidGlobal() && url.GetScheme() == THttpURL::SchemeHTTPS)
+#ifdef USE_GNUTLS
+ if (url.IsValidGlobal() && url.GetScheme() == THttpURL::SchemeHTTPS)
return new socketSecureHandler;
-#endif
+#endif
return nullptr;
}
diff --git a/library/cpp/http/fetch/httpfetcher.h b/library/cpp/http/fetch/httpfetcher.h
index 4b02eef5fc..7fc251afd2 100644
--- a/library/cpp/http/fetch/httpfetcher.h
+++ b/library/cpp/http/fetch/httpfetcher.h
@@ -1,7 +1,7 @@
#pragma once
#ifdef _MSC_VER
-#include <io.h>
+#include <io.h>
#endif
#include <library/cpp/http/misc/httpdate.h>
@@ -10,27 +10,27 @@
#include "httpparser.h"
struct TFakeBackup {
- int Write(void* /*buf*/, size_t /*size*/) {
- return 0;
- }
+ int Write(void* /*buf*/, size_t /*size*/) {
+ return 0;
+ }
};
template <size_t bufsize = 5000>
struct TFakeAlloc {
- void Shrink(void* /*buf*/, size_t /*size*/) {
- }
- void* Grab(size_t /*min*/, size_t* real) {
- *real = bufsize;
- return buf;
- }
- char buf[bufsize];
+ void Shrink(void* /*buf*/, size_t /*size*/) {
+ }
+ void* Grab(size_t /*min*/, size_t* real) {
+ *real = bufsize;
+ return buf;
+ }
+ char buf[bufsize];
};
-template <typename TAlloc = TFakeAlloc<>,
- typename TCheck = TFakeCheck<>,
+template <typename TAlloc = TFakeAlloc<>,
+ typename TCheck = TFakeCheck<>,
typename TWriter = TFakeBackup,
- typename TAgent = THttpAgent<>>
-class THttpFetcher: public THttpParser<TCheck>, public TAlloc, public TWriter, public TAgent {
+ typename TAgent = THttpAgent<>>
+class THttpFetcher: public THttpParser<TCheck>, public TAlloc, public TWriter, public TAgent {
public:
static const size_t TCP_MIN = 1500;
static int TerminateNow;
@@ -40,21 +40,21 @@ public:
, TAlloc()
, TWriter()
, TAgent()
- {
- }
+ {
+ }
- virtual ~THttpFetcher() {
- }
+ virtual ~THttpFetcher() {
+ }
- int Fetch(THttpHeader* header, const char* path, const char* const* headers, int persistent, bool head_request = false) {
+ int Fetch(THttpHeader* header, const char* path, const char* const* headers, int persistent, bool head_request = false) {
int ret = 0;
int fetcherr = 0;
THttpParser<TCheck>::Init(header, head_request);
- const char* scheme = HttpUrlSchemeKindToString((THttpURL::TSchemeKind)TAgent::GetScheme());
+ const char* scheme = HttpUrlSchemeKindToString((THttpURL::TSchemeKind)TAgent::GetScheme());
size_t schemelen = strlen(scheme);
if (*path == '/') {
- header->base = TStringBuf(scheme, schemelen);
+ header->base = TStringBuf(scheme, schemelen);
header->base += TStringBuf("://", 3);
header->base += TStringBuf(TAgent::pHostBeg, TAgent::pHostEnd - TAgent::pHostBeg);
header->base += path;
@@ -95,9 +95,9 @@ public:
}
if ((got = TAgent::read(bufptr, buffree)) < 0) {
fetcherr = errno;
- if (errno == EINTR)
+ if (errno == EINTR)
header->error = HTTP_INTERRUPTED;
- else if (errno == ETIMEDOUT)
+ else if (errno == ETIMEDOUT)
header->error = HTTP_TIMEDOUT_WHILE_BYTES_RECEIVING;
else
header->error = HTTP_CONNECTION_LOST;
@@ -113,7 +113,7 @@ public:
THttpParser<TCheck>::Parse(parsebuf, got);
if (header->error)
- break; //if ANY error ocurred we will stop download that file or will have unprognosed stream position until MAX size reached
+ break; //if ANY error ocurred we will stop download that file or will have unprognosed stream position until MAX size reached
if (inheader && THttpParser<TCheck>::GetState() != THttpParser<TCheck>::hp_in_header) {
inheader = 0;
@@ -141,12 +141,12 @@ public:
i64 Adjustment = 0;
if (!header->error) {
- if (header->transfer_chunked) {
+ if (header->transfer_chunked) {
Adjustment = header->header_size + header->entity_size - bufsize - 1;
- } else if (header->content_length >= 0) {
+ } else if (header->content_length >= 0) {
Adjustment = header->header_size + header->content_length - bufsize;
}
- if (Adjustment > 0)
+ if (Adjustment > 0)
Adjustment = 0;
}
diff --git a/library/cpp/http/fetch/httpfsm.h b/library/cpp/http/fetch/httpfsm.h
index af490adc5a..c4abdcd0d2 100644
--- a/library/cpp/http/fetch/httpfsm.h
+++ b/library/cpp/http/fetch/httpfsm.h
@@ -1,7 +1,7 @@
#pragma once
-#include "httpheader.h"
-
+#include "httpheader.h"
+
#include <util/system/maxlen.h>
#include <util/datetime/parser.h>
@@ -15,7 +15,7 @@ struct THttpHeaderParser {
static constexpr int NeedMore = 1;
static constexpr int Accepted = 2;
- int Execute(const void* inBuf, size_t len) {
+ int Execute(const void* inBuf, size_t len) {
return execute((unsigned char*)inBuf, (int)len);
}
@@ -23,7 +23,7 @@ struct THttpHeaderParser {
return Execute(str.data(), str.size());
}
- int Init(THttpHeader* h) {
+ int Init(THttpHeader* h) {
int ret = Init((THttpBaseHeader*)(h));
hd = h;
hd->Init();
@@ -32,43 +32,43 @@ struct THttpHeaderParser {
return ret;
}
- int Init(THttpAuthHeader* h) {
+ int Init(THttpAuthHeader* h) {
int ret = Init((THttpHeader*)(h));
auth_hd = h;
return ret;
}
- int Init(THttpRequestHeader* h) {
+ int Init(THttpRequestHeader* h) {
int ret = Init((THttpBaseHeader*)(h));
request_hd = h;
request_hd->Init();
return ret;
}
- THttpHeader* hd;
- long I;
- int Dc;
+ THttpHeader* hd;
+ long I;
+ int Dc;
TDateTimeFieldsDeprecated DateTimeFields;
- char buf[FETCHER_URL_MAX];
- size_t buflen;
- char* lastchar;
+ char buf[FETCHER_URL_MAX];
+ size_t buflen;
+ char* lastchar;
- const unsigned char* langstart;
- size_t langlen;
+ const unsigned char* langstart;
+ size_t langlen;
- char* hreflangpos;
- size_t hreflangspace;
+ char* hreflangpos;
+ size_t hreflangspace;
bool AcceptingXRobots;
- THttpAuthHeader* auth_hd;
- THttpRequestHeader* request_hd;
+ THttpAuthHeader* auth_hd;
+ THttpRequestHeader* request_hd;
private:
- THttpBaseHeader* base_hd;
+ THttpBaseHeader* base_hd;
int cs;
-
+
private:
- int Init(THttpBaseHeader* header) {
+ int Init(THttpBaseHeader* header) {
base_hd = header;
auth_hd = nullptr;
request_hd = nullptr;
@@ -77,12 +77,12 @@ private:
return 0;
}
- int execute(unsigned char* inBuf, int len);
+ int execute(unsigned char* inBuf, int len);
void init();
};
struct THttpChunkParser {
- int Execute(const void* inBuf, int len) {
+ int Execute(const void* inBuf, int len) {
return execute((unsigned char*)inBuf, len);
}
@@ -91,14 +91,14 @@ struct THttpChunkParser {
return 0;
}
- int chunk_length;
- char* lastchar;
- long I;
- int Dc;
- i64 cnt64;
+ int chunk_length;
+ char* lastchar;
+ long I;
+ int Dc;
+ i64 cnt64;
private:
int cs;
- int execute(unsigned char* inBuf, int len);
+ int execute(unsigned char* inBuf, int len);
void init();
};
diff --git a/library/cpp/http/fetch/httpfsm_ut.cpp b/library/cpp/http/fetch/httpfsm_ut.cpp
index d6393abd48..b018e80101 100644
--- a/library/cpp/http/fetch/httpfsm_ut.cpp
+++ b/library/cpp/http/fetch/httpfsm_ut.cpp
@@ -1,22 +1,22 @@
-#include "httpfsm.h"
+#include "httpfsm.h"
#include "library-htfetch_ut_hreflang_in.h"
#include "library-htfetch_ut_hreflang_out.h"
-
+
#include <util/generic/ptr.h>
#include <library/cpp/charset/doccodes.h>
#include <library/cpp/testing/unittest/registar.h>
class THttpHeaderParserTestSuite: public TTestBase {
UNIT_TEST_SUITE(THttpHeaderParserTestSuite);
- UNIT_TEST(TestRequestHeader);
- UNIT_TEST(TestSplitRequestHeader);
- UNIT_TEST(TestTrailingData);
- UNIT_TEST(TestProxyRequestHeader);
- UNIT_TEST(TestIncorrectRequestHeader);
- UNIT_TEST(TestLastModified);
- UNIT_TEST(TestLastModifiedCorrupted);
- UNIT_TEST(TestResponseHeaderOnRequest);
- UNIT_TEST(TestRequestHeaderOnResponse);
+ UNIT_TEST(TestRequestHeader);
+ UNIT_TEST(TestSplitRequestHeader);
+ UNIT_TEST(TestTrailingData);
+ UNIT_TEST(TestProxyRequestHeader);
+ UNIT_TEST(TestIncorrectRequestHeader);
+ UNIT_TEST(TestLastModified);
+ UNIT_TEST(TestLastModifiedCorrupted);
+ UNIT_TEST(TestResponseHeaderOnRequest);
+ UNIT_TEST(TestRequestHeaderOnResponse);
UNIT_TEST(TestXRobotsTagUnknownTags);
UNIT_TEST(TestXRobotsTagMyBot);
UNIT_TEST(TestXRobotsTagOtherBot);
@@ -25,20 +25,20 @@ class THttpHeaderParserTestSuite: public TTestBase {
UNIT_TEST(TestXRobotsTagOverridePriority);
UNIT_TEST(TestXRobotsTagDoesNotBreakCharset);
UNIT_TEST(TestXRobotsTagAllowsMultiline);
- UNIT_TEST(TestRelCanonical);
- UNIT_TEST(TestHreflang);
- UNIT_TEST(TestHreflangOnLongInput);
- UNIT_TEST(TestMimeType);
+ UNIT_TEST(TestRelCanonical);
+ UNIT_TEST(TestHreflang);
+ UNIT_TEST(TestHreflangOnLongInput);
+ UNIT_TEST(TestMimeType);
UNIT_TEST(TestRepeatedContentEncoding);
UNIT_TEST_SUITE_END();
-
+
private:
THolder<THttpHeaderParser> httpHeaderParser;
-
+
private:
void TestStart();
void TestFinish();
-
+
public:
void TestRequestHeader();
void TestSplitRequestHeader();
@@ -76,8 +76,8 @@ void THttpHeaderParserTestSuite::TestRequestHeader() {
TestStart();
THttpRequestHeader httpRequestHeader;
httpHeaderParser->Init(&httpRequestHeader);
- const char* request = "GET /search?q=hi HTTP/1.1\r\n"
- "Host: www.google.ru:8080\r\n\r\n";
+ const char* request = "GET /search?q=hi HTTP/1.1\r\n"
+ "Host: www.google.ru:8080\r\n\r\n";
i32 result = httpHeaderParser->Execute(request, strlen(request));
UNIT_ASSERT_EQUAL(result, 2);
UNIT_ASSERT_EQUAL(httpRequestHeader.http_method, HTTP_METHOD_GET);
@@ -85,11 +85,11 @@ void THttpHeaderParserTestSuite::TestRequestHeader() {
UNIT_ASSERT_EQUAL(httpRequestHeader.request_uri, "/search?q=hi");
UNIT_ASSERT_EQUAL(httpRequestHeader.GetUrl(), "http://www.google.ru:8080/search?q=hi");
UNIT_ASSERT_EQUAL(httpHeaderParser->lastchar - request + 1,
- (i32)strlen(request));
+ (i32)strlen(request));
UNIT_ASSERT_EQUAL(httpRequestHeader.x_yandex_response_timeout,
- DEFAULT_RESPONSE_TIMEOUT);
+ DEFAULT_RESPONSE_TIMEOUT);
UNIT_ASSERT_EQUAL(httpRequestHeader.x_yandex_request_priority,
- DEFAULT_REQUEST_PRIORITY);
+ DEFAULT_REQUEST_PRIORITY);
UNIT_ASSERT_EQUAL(strcmp(httpRequestHeader.x_yandex_sourcename, ""), 0);
UNIT_ASSERT_EQUAL(strcmp(httpRequestHeader.x_yandex_requesttype, ""), 0);
UNIT_ASSERT_EQUAL(strcmp(httpRequestHeader.x_yandex_fetchoptions, ""), 0);
@@ -99,7 +99,7 @@ void THttpHeaderParserTestSuite::TestRequestHeader() {
void THttpHeaderParserTestSuite::TestSplitRequestHeader() {
TestStart();
- const char* request =
+ const char* request =
"GET /search?q=hi HTTP/1.1\r\n"
"Host: www.google.ru:8080 \r\n"
"\r\n";
@@ -108,8 +108,8 @@ void THttpHeaderParserTestSuite::TestSplitRequestHeader() {
for (size_t n1 = 0; n1 < rlen; n1++) {
for (size_t n2 = n1; n2 < rlen; n2++) {
TString s1{request, 0, n1};
- TString s2{request, n1, n2 - n1};
- TString s3{request, n2, rlen - n2};
+ TString s2{request, n1, n2 - n1};
+ TString s3{request, n2, rlen - n2};
UNIT_ASSERT_EQUAL(s1 + s2 + s3, request);
THttpRequestHeader httpRequestHeader;
@@ -134,7 +134,7 @@ void THttpHeaderParserTestSuite::TestTrailingData() {
TestStart();
THttpRequestHeader httpRequestHeader;
UNIT_ASSERT(0 == httpHeaderParser->Init(&httpRequestHeader));
- const char* request =
+ const char* request =
"GET /search?q=hi HTTP/1.1\r\n"
"Host: www.google.ru:8080\r\n"
"\r\n"
@@ -156,7 +156,7 @@ void THttpHeaderParserTestSuite::TestProxyRequestHeader() {
TestStart();
THttpRequestHeader httpRequestHeader;
httpHeaderParser->Init(&httpRequestHeader);
- const char* request =
+ const char* request =
"GET http://www.google.ru:8080/search?q=hi HTTP/1.1\r\n"
"X-Yandex-Response-Timeout: 1000\r\n"
"X-Yandex-Request-Priority: 2\r\n"
@@ -179,16 +179,16 @@ void THttpHeaderParserTestSuite::TestProxyRequestHeader() {
UNIT_ASSERT_VALUES_EQUAL(httpRequestHeader.if_modified_since,
TInstant::ParseIso8601Deprecated("1994-10-29 19:43:31Z").TimeT());
UNIT_ASSERT_EQUAL(httpRequestHeader.request_uri,
- "http://www.google.ru:8080/search?q=hi");
- UNIT_ASSERT(httpRequestHeader.GetUrl() ==
+ "http://www.google.ru:8080/search?q=hi");
+ UNIT_ASSERT(httpRequestHeader.GetUrl() ==
"http://www.google.ru:8080/search?q=hi");
UNIT_ASSERT_EQUAL(strcmp(httpRequestHeader.host, ""), 0);
UNIT_ASSERT_EQUAL(strcmp(httpRequestHeader.from, "webadmin@yandex.ru"), 0);
UNIT_ASSERT_EQUAL(strcmp(httpRequestHeader.user_agent,
- "Yandex/1.01.001 (compatible; Win16; I)"),
- 0);
+ "Yandex/1.01.001 (compatible; Win16; I)"),
+ 0);
UNIT_ASSERT_EQUAL(httpHeaderParser->lastchar - request + 1,
- (i32)strlen(request));
+ (i32)strlen(request));
TestFinish();
}
@@ -196,8 +196,8 @@ void THttpHeaderParserTestSuite::TestIncorrectRequestHeader() {
TestStart();
THttpRequestHeader httpRequestHeader;
httpHeaderParser->Init(&httpRequestHeader);
- const char* request = "GET /search?q=hi HTP/1.1\r\n"
- "Host: www.google.ru:8080\r\n\r\n";
+ const char* request = "GET /search?q=hi HTP/1.1\r\n"
+ "Host: www.google.ru:8080\r\n\r\n";
i32 result = httpHeaderParser->Execute(request, strlen(request));
UNIT_ASSERT(result != 2);
TestFinish();
@@ -214,7 +214,7 @@ void THttpHeaderParserTestSuite::TestLastModified() {
UNIT_ASSERT(2 == httpHeaderParser->Execute(headers, strlen(headers)));
UNIT_ASSERT_VALUES_EQUAL(
TInstant::ParseIso8601Deprecated("2009-08-13 14:27:08Z").TimeT(),
- h.http_time);
+ h.http_time);
TestFinish();
}
@@ -235,7 +235,7 @@ void THttpHeaderParserTestSuite::TestXRobotsTagUnknownTags() {
TestStart();
THttpHeader httpHeader;
httpHeaderParser->Init(&httpHeader);
- const char* headers =
+ const char* headers =
"HTTP/1.1 200 OK\r\n"
"Content-Type: text/html\r\n"
"x-robots-tag: asdfasdf asdf asdf,,, , noindex,noodpXXX , NOFOLLOW ,noodpnofollow\r\n\r\n";
@@ -384,7 +384,7 @@ void THttpHeaderParserTestSuite::TestHreflang() {
TestStart();
THttpHeader httpHeader;
httpHeaderParser->Init(&httpHeader);
- const char* headers =
+ const char* headers =
"HTTP/1.1 200 OK\r\n"
"Content-Type: text/html\r\n"
"link: <http://www.high.ru/>; rel='alternate'; hreflang='x-default'\r\n"
@@ -414,7 +414,7 @@ void THttpHeaderParserTestSuite::TestRelCanonical() {
TestStart();
THttpHeader httpHeader;
httpHeaderParser->Init(&httpHeader);
- const char* headers =
+ const char* headers =
"HTTP/1.1 200 OK\r\n"
"Content-Type: text/html\r\n"
"Link: <http://yandex.ru>; rel = \"canonical\"\r\n\r\n";
@@ -428,8 +428,8 @@ void THttpHeaderParserTestSuite::TestResponseHeaderOnRequest() {
TestStart();
THttpHeader httpHeader;
httpHeaderParser->Init(&httpHeader);
- const char* request = "GET /search?q=hi HTP/1.1\r\n"
- "Host: www.google.ru:8080\r\n\r\n";
+ const char* request = "GET /search?q=hi HTP/1.1\r\n"
+ "Host: www.google.ru:8080\r\n\r\n";
i32 result = httpHeaderParser->Execute(request, strlen(request));
UNIT_ASSERT_EQUAL(result, -3);
TestFinish();
@@ -439,9 +439,9 @@ void THttpHeaderParserTestSuite::TestRequestHeaderOnResponse() {
TestStart();
THttpRequestHeader httpRequestHeader;
httpHeaderParser->Init(&httpRequestHeader);
- const char* response = "HTTP/1.1 200 OK\r\n"
- "Content-Type: text/html\r\n"
- "Last-Modified: Thu, 13 Aug 2009 14:\r\n\r\n";
+ const char* response = "HTTP/1.1 200 OK\r\n"
+ "Content-Type: text/html\r\n"
+ "Last-Modified: Thu, 13 Aug 2009 14:\r\n\r\n";
i32 result = httpHeaderParser->Execute(response, strlen(response));
UNIT_ASSERT_EQUAL(result, -3);
TestFinish();
@@ -451,13 +451,13 @@ void THttpHeaderParserTestSuite::TestMimeType() {
TestStart();
THttpHeader httpHeader;
httpHeaderParser->Init(&httpHeader);
- const char* headers =
+ const char* headers =
"HTTP/1.1 200 OK\r\n"
"Content-Type: application/json; charset=utf-8\r\n\r\n";
i32 result = httpHeaderParser->Execute(headers, strlen(headers));
UNIT_ASSERT_EQUAL(result, 2);
UNIT_ASSERT_EQUAL(httpHeader.mime_type, static_cast<ui8>(MIME_JSON));
- UNIT_ASSERT_EQUAL(httpHeader.charset, static_cast<ui8>(CODES_UTF8));
+ UNIT_ASSERT_EQUAL(httpHeader.charset, static_cast<ui8>(CODES_UTF8));
TestFinish();
}
@@ -516,10 +516,10 @@ Y_UNIT_TEST_SUITE(TestHttpChunkParser) {
Y_UNIT_TEST(TestWithoutEolHead) {
const TStringBuf blob{
"4\r\n"
- "____\r\n"};
+ "____\r\n"};
TVector<int> states{
- -1, /* 1, -1,
- 1, -1, 1, -1, 1, -1 */};
+ -1, /* 1, -1,
+ 1, -1, 1, -1, 1, -1 */};
// as soon as error happens parser state should be considered
// undefined, state is meaningless after the very first `-1`
// moreover, testenv produces `states[1] == -1` for this input and
@@ -530,7 +530,7 @@ Y_UNIT_TEST_SUITE(TestHttpChunkParser) {
Y_UNIT_TEST(TestTrivialChunk) {
const TStringBuf blob{
"\r\n"
- "4\r\n"};
+ "4\r\n"};
THttpChunkParser parser(parseBytesWithLastState(blob, 2));
UNIT_ASSERT_EQUAL(parser.chunk_length, 4);
UNIT_ASSERT_EQUAL(parser.cnt64, 4);
@@ -539,18 +539,18 @@ Y_UNIT_TEST_SUITE(TestHttpChunkParser) {
Y_UNIT_TEST(TestNegative) {
const TStringBuf blob{
"\r\n"
- "-1"};
+ "-1"};
TVector<int> states{
1, 1,
- -1,
- /* 1 */};
+ -1,
+ /* 1 */};
parseByteByByte(blob, states);
}
Y_UNIT_TEST(TestLeadingZero) {
const TStringBuf blob{
"\r\n"
- "042\r\n"};
+ "042\r\n"};
THttpChunkParser parser(parseBytesWithLastState(blob, 2));
UNIT_ASSERT_EQUAL(parser.chunk_length, 0x42);
}
@@ -558,7 +558,7 @@ Y_UNIT_TEST_SUITE(TestHttpChunkParser) {
Y_UNIT_TEST(TestIntOverflow) {
const TStringBuf blob{
"\r\n"
- "deadbeef"};
+ "deadbeef"};
THttpChunkParser parser(parseBytesWithLastState(blob, -2));
UNIT_ASSERT_EQUAL(parser.chunk_length, 0);
UNIT_ASSERT_EQUAL(parser.cnt64, 0xdeadbeef);
@@ -571,9 +571,9 @@ Y_UNIT_TEST_SUITE(TestHttpChunkParser) {
"_" // first byte of the chunk
};
TVector<int> states{
- 1, 1,
- 1, 1, 2,
- -1};
+ 1, 1,
+ 1, 1, 2,
+ -1};
parseByteByByte(blob, states);
}
@@ -584,7 +584,7 @@ Y_UNIT_TEST_SUITE(TestHttpChunkParser) {
"\r\n"
"000 ;foo = bar \r\n"
"Trailer: bar\r\n"
- "\r\n"};
+ "\r\n"};
THttpChunkParser parser(parseBytesWithLastState(blob, 2));
UNIT_ASSERT_EQUAL(parser.chunk_length, 0);
}
diff --git a/library/cpp/http/fetch/httpheader.h b/library/cpp/http/fetch/httpheader.h
index e779cb08ec..b2810bbd41 100644
--- a/library/cpp/http/fetch/httpheader.h
+++ b/library/cpp/http/fetch/httpheader.h
@@ -10,33 +10,33 @@
#include <util/generic/ylimits.h>
#include <util/system/maxlen.h>
-#include <ctime>
+#include <ctime>
#include <cstdio>
#include <cstdlib>
#include <cstring>
-#include <algorithm>
+#include <algorithm>
// This is ugly solution but here a lot of work to do it the right way.
#define FETCHER_URL_MAX 8192
-extern const i64 DEFAULT_RETRY_AFTER; /// == -1
+extern const i64 DEFAULT_RETRY_AFTER; /// == -1
extern const i64 DEFAULT_IF_MODIFIED_SINCE; /// == -1
-extern const i32 DEFAULT_MAX_AGE; /// == -1
-extern const i8 DEFAULT_REQUEST_PRIORITY; /// == -1
-extern const i32 DEFAULT_RESPONSE_TIMEOUT; /// == -1
+extern const i32 DEFAULT_MAX_AGE; /// == -1
+extern const i8 DEFAULT_REQUEST_PRIORITY; /// == -1
+extern const i32 DEFAULT_RESPONSE_TIMEOUT; /// == -1
#define HTTP_PREFIX "http://"
#define MAX_LANGREGION_LEN 4
#define MAXWORD_LEN 55
enum HTTP_COMPRESSION {
- HTTP_COMPRESSION_UNSET = 0,
- HTTP_COMPRESSION_ERROR = 1,
+ HTTP_COMPRESSION_UNSET = 0,
+ HTTP_COMPRESSION_ERROR = 1,
HTTP_COMPRESSION_IDENTITY = 2,
- HTTP_COMPRESSION_GZIP = 3,
- HTTP_COMPRESSION_DEFLATE = 4,
+ HTTP_COMPRESSION_GZIP = 3,
+ HTTP_COMPRESSION_DEFLATE = 4,
HTTP_COMPRESSION_COMPRESS = 5,
- HTTP_COMPRESSION_MAX = 6
+ HTTP_COMPRESSION_MAX = 6
};
enum HTTP_METHOD {
@@ -61,22 +61,22 @@ enum HTTP_CONNECTION {
/// Class represents general http header fields.
struct THttpBaseHeader {
public:
- i16 error;
- i32 header_size;
- i32 entity_size;
- i64 content_length;
- i64 http_time; // seconds since epoch
- i64 content_range_start; // Content-Range: first-byte-pos
- i64 content_range_end; // Content-Range: last-byte-pos
- i64 content_range_entity_length; // Content-Range: entity-length
- i8 http_minor;
- i8 mime_type;
- i8 charset;
- i8 compression_method;
- i8 transfer_chunked;
- i8 connection_closed;
+ i16 error;
+ i32 header_size;
+ i32 entity_size;
+ i64 content_length;
+ i64 http_time; // seconds since epoch
+ i64 content_range_start; // Content-Range: first-byte-pos
+ i64 content_range_end; // Content-Range: last-byte-pos
+ i64 content_range_entity_length; // Content-Range: entity-length
+ i8 http_minor;
+ i8 mime_type;
+ i8 charset;
+ i8 compression_method;
+ i8 transfer_chunked;
+ i8 connection_closed;
TString base;
-
+
public:
void Init() {
error = 0;
@@ -113,8 +113,8 @@ public:
}
int SetBase(const char* path,
- const char* hostNamePtr = nullptr,
- int hostNameLength = 0) {
+ const char* hostNamePtr = nullptr,
+ int hostNameLength = 0) {
if (*path == '/') {
base = "http://";
base += TStringBuf(hostNamePtr, hostNameLength);
@@ -130,16 +130,16 @@ enum { HREFLANG_MAX = FETCHER_URL_MAX * 2 };
/// Class represents Http Response Header.
struct THttpHeader: public THttpBaseHeader {
public:
- i8 accept_ranges;
- i8 squid_error;
+ i8 accept_ranges;
+ i8 squid_error;
i8 x_robots_tag; // deprecated, use x_robots_state instead
- i16 http_status;
+ i16 http_status;
TString location;
TString rel_canonical;
- char hreflangs[HREFLANG_MAX];
- i64 retry_after;
+ char hreflangs[HREFLANG_MAX];
+ i64 retry_after;
TString x_robots_state; // 'xxxxx' format, see `library/html/zoneconf/parsefunc.cpp`
-
+
public:
void Init() {
THttpBaseHeader::Init();
@@ -174,12 +174,12 @@ public:
char x_yandex_sourcename[MAXWORD_LEN];
char x_yandex_requesttype[MAXWORD_LEN];
char x_yandex_fetchoptions[MAXWORD_LEN];
- i8 http_method;
- i8 x_yandex_request_priority;
- i32 x_yandex_response_timeout;
- i32 max_age;
- i64 if_modified_since;
-
+ i8 http_method;
+ i8 x_yandex_request_priority;
+ i32 x_yandex_response_timeout;
+ i32 max_age;
+ i64 if_modified_since;
+
public:
THttpRequestHeader() {
Init();
@@ -229,7 +229,7 @@ public:
return url;
}
- char* GetUrl(char* buffer, size_t size) {
+ char* GetUrl(char* buffer, size_t size) {
if (host[0] == 0 || !strcmp(host, "")) {
strlcpy(buffer, request_uri.c_str(), size);
} else {
@@ -244,27 +244,27 @@ public:
char* realm;
char* nonce;
char* opaque;
- bool stale;
- int algorithm;
- bool qop_auth;
- bool use_auth;
+ bool stale;
+ int algorithm;
+ bool qop_auth;
+ bool use_auth;
//we do not provide auth-int variant as too heavy
//bool qop_auth_int;
- THttpAuthHeader()
- : realm(nullptr)
- , nonce(nullptr)
- , opaque(nullptr)
- , stale(false)
- , algorithm(0)
- , qop_auth(false)
- , use_auth(true)
+ THttpAuthHeader()
+ : realm(nullptr)
+ , nonce(nullptr)
+ , opaque(nullptr)
+ , stale(false)
+ , algorithm(0)
+ , qop_auth(false)
+ , use_auth(true)
{
THttpHeader::Init();
}
- ~THttpAuthHeader() {
+ ~THttpAuthHeader() {
free(realm);
free(nonce);
free(opaque);
@@ -272,7 +272,7 @@ public:
void Print() {
THttpHeader::Print();
- if (use_auth) {
+ if (use_auth) {
if (realm)
printf("realm: \"%s\"\n", realm);
if (nonce)
diff --git a/library/cpp/http/fetch/httpload.cpp b/library/cpp/http/fetch/httpload.cpp
index 975a8d792c..82ea8900b5 100644
--- a/library/cpp/http/fetch/httpload.cpp
+++ b/library/cpp/http/fetch/httpload.cpp
@@ -2,210 +2,210 @@
/************************************************************/
/************************************************************/
-httpAgentReader::httpAgentReader(httpSpecialAgent& agent,
- const char* baseUrl,
- bool assumeConnectionClosed,
- bool use_auth,
- int bufSize)
- : Header_()
- , Agent_(agent)
- , Buffer_(new char[bufSize])
- , BufPtr_(Buffer_)
- , BufSize_(bufSize)
- , BufRest_(0)
+httpAgentReader::httpAgentReader(httpSpecialAgent& agent,
+ const char* baseUrl,
+ bool assumeConnectionClosed,
+ bool use_auth,
+ int bufSize)
+ : Header_()
+ , Agent_(agent)
+ , Buffer_(new char[bufSize])
+ , BufPtr_(Buffer_)
+ , BufSize_(bufSize)
+ , BufRest_(0)
{
HeadRequest = false;
- Header = &Header_;
+ Header = &Header_;
if (use_auth)
- HeaderParser.Init(&Header_);
+ HeaderParser.Init(&Header_);
else
HeaderParser.Init(Header);
- setAssumeConnectionClosed(assumeConnectionClosed ? 1 : 0);
- Header_.SetBase(baseUrl);
+ setAssumeConnectionClosed(assumeConnectionClosed ? 1 : 0);
+ Header_.SetBase(baseUrl);
- if (Header_.error)
+ if (Header_.error)
State = hp_error;
else
State = hp_in_header;
}
/************************************************************/
-httpAgentReader::~httpAgentReader() {
- delete[] Buffer_;
+httpAgentReader::~httpAgentReader() {
+ delete[] Buffer_;
}
/************************************************************/
-void httpAgentReader::readBuf() {
- assert(BufRest_ == 0);
- if (!BufPtr_) {
- BufRest_ = -1;
+void httpAgentReader::readBuf() {
+ assert(BufRest_ == 0);
+ if (!BufPtr_) {
+ BufRest_ = -1;
return;
}
- BufRest_ = Agent_.read(Buffer_, BufSize_);
- if (BufRest_ <= 0) {
- BufRest_ = -1;
- BufPtr_ = nullptr;
+ BufRest_ = Agent_.read(Buffer_, BufSize_);
+ if (BufRest_ <= 0) {
+ BufRest_ = -1;
+ BufPtr_ = nullptr;
} else {
- BufPtr_ = Buffer_;
-
+ BufPtr_ = Buffer_;
+
//cout << "BUF: " << mBuffer << endl << endl;
}
}
/************************************************************/
-const THttpHeader* httpAgentReader::readHeader() {
- while (State == hp_in_header) {
- if (!step()) {
- Header_.error = HTTP_CONNECTION_LOST;
+const THttpHeader* httpAgentReader::readHeader() {
+ while (State == hp_in_header) {
+ if (!step()) {
+ Header_.error = HTTP_CONNECTION_LOST;
return nullptr;
}
- ParseGeneric(BufPtr_, BufRest_);
+ ParseGeneric(BufPtr_, BufRest_);
}
- if (State == hp_eof || State == hp_error) {
+ if (State == hp_eof || State == hp_error) {
BufPtr_ = nullptr;
- BufRest_ = -1;
+ BufRest_ = -1;
}
- if (State == hp_error || Header_.error)
+ if (State == hp_error || Header_.error)
return nullptr;
- return &Header_;
+ return &Header_;
}
/************************************************************/
-long httpAgentReader::readPortion(void*& buf) {
- assert(State != hp_in_header);
+long httpAgentReader::readPortion(void*& buf) {
+ assert(State != hp_in_header);
long Chunk = 0;
- do {
- if (BufSize_ == 0 && !BufPtr_)
+ do {
+ if (BufSize_ == 0 && !BufPtr_)
return 0;
if (!step())
return 0;
- Chunk = ParseGeneric(BufPtr_, BufRest_);
- buf = BufPtr_;
+ Chunk = ParseGeneric(BufPtr_, BufRest_);
+ buf = BufPtr_;
- if (State == hp_error && Header_.entity_size > Header_.content_length) {
- Chunk -= (Header_.entity_size - Header_.content_length);
- BufPtr_ = (char*)BufPtr_ + Chunk;
- BufRest_ = 0;
- State = hp_eof;
- Header_.error = 0;
+ if (State == hp_error && Header_.entity_size > Header_.content_length) {
+ Chunk -= (Header_.entity_size - Header_.content_length);
+ BufPtr_ = (char*)BufPtr_ + Chunk;
+ BufRest_ = 0;
+ State = hp_eof;
+ Header_.error = 0;
break;
}
- BufPtr_ = (char*)BufPtr_ + Chunk;
- BufRest_ -= Chunk;
+ BufPtr_ = (char*)BufPtr_ + Chunk;
+ BufRest_ -= Chunk;
- if (State == hp_eof || State == hp_error) {
- BufRest_ = -1;
- BufPtr_ = nullptr;
+ if (State == hp_eof || State == hp_error) {
+ BufRest_ = -1;
+ BufPtr_ = nullptr;
}
} while (!Chunk);
return Chunk;
}
/************************************************************/
-bool httpAgentReader::skipTheRest() {
+bool httpAgentReader::skipTheRest() {
void* b;
while (!eof())
readPortion(b);
- return (State == hp_eof);
+ return (State == hp_eof);
}
/************************************************************/
/************************************************************/
-httpLoadAgent::httpLoadAgent(bool handleAuthorization,
- socketHandlerFactory& factory)
- : Factory_(factory)
- , HandleAuthorization_(handleAuthorization)
- , URL_()
- , PersistentConn_(false)
- , Reader_(nullptr)
- , Headers_()
- , ErrCode_(0)
- , RealHost_(nullptr)
+httpLoadAgent::httpLoadAgent(bool handleAuthorization,
+ socketHandlerFactory& factory)
+ : Factory_(factory)
+ , HandleAuthorization_(handleAuthorization)
+ , URL_()
+ , PersistentConn_(false)
+ , Reader_(nullptr)
+ , Headers_()
+ , ErrCode_(0)
+ , RealHost_(nullptr)
{
}
/************************************************************/
-httpLoadAgent::~httpLoadAgent() {
- delete Reader_;
- free(RealHost_);
+httpLoadAgent::~httpLoadAgent() {
+ delete Reader_;
+ free(RealHost_);
}
/************************************************************/
-void httpLoadAgent::clearReader() {
- if (Reader_) {
+void httpLoadAgent::clearReader() {
+ if (Reader_) {
bool opened = false;
- if (PersistentConn_) {
- const THttpHeader* H = Reader_->readHeader();
- if (H && !H->connection_closed) {
- Reader_->skipTheRest();
+ if (PersistentConn_) {
+ const THttpHeader* H = Reader_->readHeader();
+ if (H && !H->connection_closed) {
+ Reader_->skipTheRest();
opened = true;
}
}
if (!opened)
Disconnect();
- delete Reader_;
+ delete Reader_;
Reader_ = nullptr;
}
- ErrCode_ = 0;
+ ErrCode_ = 0;
}
/************************************************************/
-void httpLoadAgent::setRealHost(const char* hostname) {
- free(RealHost_);
+void httpLoadAgent::setRealHost(const char* hostname) {
+ free(RealHost_);
if (hostname)
- RealHost_ = strdup(hostname);
+ RealHost_ = strdup(hostname);
else
RealHost_ = nullptr;
- ErrCode_ = 0;
+ ErrCode_ = 0;
}
/************************************************************/
-void httpLoadAgent::setIMS(const char* ifModifiedSince) {
+void httpLoadAgent::setIMS(const char* ifModifiedSince) {
char ims_buf[100];
snprintf(ims_buf, 100, "If-Modified-Since: %s\r\n",
ifModifiedSince);
- Headers_.push_back(ims_buf);
+ Headers_.push_back(ims_buf);
}
/************************************************************/
-void httpLoadAgent::addHeaderInstruction(const char* instr) {
- Headers_.push_back(instr);
+void httpLoadAgent::addHeaderInstruction(const char* instr) {
+ Headers_.push_back(instr);
}
/************************************************************/
-void httpLoadAgent::dropHeaderInstructions() {
- Headers_.clear();
+void httpLoadAgent::dropHeaderInstructions() {
+ Headers_.clear();
}
/************************************************************/
-bool httpLoadAgent::startRequest(const THttpURL& url,
- bool persistent,
- const TAddrList& addrs)
+bool httpLoadAgent::startRequest(const THttpURL& url,
+ bool persistent,
+ const TAddrList& addrs)
{
clearReader();
- ErrCode_ = 0;
+ ErrCode_ = 0;
- URL_.Clear();
- URL_ = url;
- PersistentConn_ = persistent;
- if (!URL_.IsValidAbs())
+ URL_.Clear();
+ URL_ = url;
+ PersistentConn_ = persistent;
+ if (!URL_.IsValidAbs())
return false;
- if (!HandleAuthorization_ && !URL_.IsNull(THttpURL::FlagAuth))
+ if (!HandleAuthorization_ && !URL_.IsNull(THttpURL::FlagAuth))
return false;
return doSetHost(addrs) && doStartRequest();
}
/************************************************************/
-bool httpLoadAgent::startRequest(const char* url,
- const char* url_to_merge,
- bool persistent,
- const TAddrList& addrs) {
+bool httpLoadAgent::startRequest(const char* url,
+ const char* url_to_merge,
+ bool persistent,
+ const TAddrList& addrs) {
clearReader();
URL_.Clear();
@@ -222,116 +222,116 @@ bool httpLoadAgent::startRequest(const char* url,
}
/************************************************************/
-bool httpLoadAgent::startRequest(const char* url,
- const char* url_to_merge,
- bool persistent,
- ui32 ip) {
+bool httpLoadAgent::startRequest(const char* url,
+ const char* url_to_merge,
+ bool persistent,
+ ui32 ip) {
clearReader();
- URL_.Clear();
- PersistentConn_ = persistent;
+ URL_.Clear();
+ PersistentConn_ = persistent;
long flags = THttpURL::FeatureSchemeKnown | THttpURL::FeaturesNormalizeSet;
- if (HandleAuthorization_)
+ if (HandleAuthorization_)
flags |= THttpURL::FeatureAuthSupported;
- if (URL_.Parse(url, flags, url_to_merge) || !URL_.IsValidGlobal())
+ if (URL_.Parse(url, flags, url_to_merge) || !URL_.IsValidGlobal())
return false;
return doSetHost(TAddrList::MakeV4Addr(ip, URL_.GetPort())) && doStartRequest();
}
/************************************************************/
-bool httpLoadAgent::doSetHost(const TAddrList& addrs) {
- socketAbstractHandler* h = Factory_.chooseHandler(URL_);
+bool httpLoadAgent::doSetHost(const TAddrList& addrs) {
+ socketAbstractHandler* h = Factory_.chooseHandler(URL_);
if (!h)
return false;
Socket.setHandler(h);
- if (addrs.size()) {
- ErrCode_ = SetHost(URL_.Get(THttpURL::FieldHost),
+ if (addrs.size()) {
+ ErrCode_ = SetHost(URL_.Get(THttpURL::FieldHost),
URL_.GetPort(), addrs);
} else {
- ErrCode_ = SetHost(URL_.Get(THttpURL::FieldHost),
- URL_.GetPort());
+ ErrCode_ = SetHost(URL_.Get(THttpURL::FieldHost),
+ URL_.GetPort());
}
- if (ErrCode_)
+ if (ErrCode_)
return false;
- if (RealHost_) {
+ if (RealHost_) {
free(Hostheader);
- Hostheader = (char*)malloc(strlen(RealHost_) + 20);
- sprintf(Hostheader, "Host: %s\r\n", RealHost_);
+ Hostheader = (char*)malloc(strlen(RealHost_) + 20);
+ sprintf(Hostheader, "Host: %s\r\n", RealHost_);
}
- if (!URL_.IsNull(THttpURL::FlagAuth)) {
- if (!HandleAuthorization_) {
- ErrCode_ = HTTP_UNAUTHORIZED;
+ if (!URL_.IsNull(THttpURL::FlagAuth)) {
+ if (!HandleAuthorization_) {
+ ErrCode_ = HTTP_UNAUTHORIZED;
return false;
}
- Digest_.setAuthorization(URL_.Get(THttpURL::FieldUsername),
- URL_.Get(THttpURL::FieldPassword));
+ Digest_.setAuthorization(URL_.Get(THttpURL::FieldUsername),
+ URL_.Get(THttpURL::FieldPassword));
}
return true;
}
/************************************************************/
-bool httpLoadAgent::setHost(const char* host_url,
- const TAddrList& addrs) {
+bool httpLoadAgent::setHost(const char* host_url,
+ const TAddrList& addrs) {
clearReader();
- URL_.Clear();
- PersistentConn_ = true;
+ URL_.Clear();
+ PersistentConn_ = true;
long flags = THttpURL::FeatureSchemeKnown | THttpURL::FeaturesNormalizeSet;
- if (HandleAuthorization_)
+ if (HandleAuthorization_)
flags |= THttpURL::FeatureAuthSupported;
- if (URL_.Parse(host_url, flags) || !URL_.IsValidGlobal())
+ if (URL_.Parse(host_url, flags) || !URL_.IsValidGlobal())
return false;
return doSetHost(addrs);
}
/************************************************************/
-bool httpLoadAgent::startOneRequest(const char* local_url) {
+bool httpLoadAgent::startOneRequest(const char* local_url) {
clearReader();
THttpURL lURL;
- if (lURL.Parse(local_url, THttpURL::FeaturesNormalizeSet) || lURL.IsValidGlobal())
+ if (lURL.Parse(local_url, THttpURL::FeaturesNormalizeSet) || lURL.IsValidGlobal())
return false;
- URL_.SetInMemory(THttpURL::FieldPath, lURL.Get(THttpURL::FieldPath));
- URL_.SetInMemory(THttpURL::FieldQuery, lURL.Get(THttpURL::FieldQuery));
- URL_.Rewrite();
+ URL_.SetInMemory(THttpURL::FieldPath, lURL.Get(THttpURL::FieldPath));
+ URL_.SetInMemory(THttpURL::FieldQuery, lURL.Get(THttpURL::FieldQuery));
+ URL_.Rewrite();
return doStartRequest();
}
/************************************************************/
-bool httpLoadAgent::doStartRequest() {
- TString urlStr = URL_.PrintS(THttpURL::FlagPath | THttpURL::FlagQuery);
+bool httpLoadAgent::doStartRequest() {
+ TString urlStr = URL_.PrintS(THttpURL::FlagPath | THttpURL::FlagQuery);
if (!urlStr)
urlStr = "/";
- for (int step = 0; step < 10; step++) {
- const char* digestHeader = Digest_.getHeaderInstruction();
+ for (int step = 0; step < 10; step++) {
+ const char* digestHeader = Digest_.getHeaderInstruction();
- unsigned i = (digestHeader) ? 2 : 1;
+ unsigned i = (digestHeader) ? 2 : 1;
const char** headers =
- (const char**)(alloca((i + Headers_.size()) * sizeof(char*)));
+ (const char**)(alloca((i + Headers_.size()) * sizeof(char*)));
- for (i = 0; i < Headers_.size(); i++)
- headers[i] = Headers_[i].c_str();
+ for (i = 0; i < Headers_.size(); i++)
+ headers[i] = Headers_[i].c_str();
if (digestHeader)
headers[i++] = digestHeader;
- headers[i] = nullptr;
+ headers[i] = nullptr;
- ErrCode_ = RequestGet(urlStr.c_str(), headers, PersistentConn_);
+ ErrCode_ = RequestGet(urlStr.c_str(), headers, PersistentConn_);
- if (ErrCode_) {
+ if (ErrCode_) {
Disconnect();
return false;
}
@@ -339,20 +339,20 @@ bool httpLoadAgent::doStartRequest() {
TString urlBaseStr = URL_.PrintS(THttpURL::FlagNoFrag);
clearReader();
- Reader_ = new httpAgentReader(*this, urlBaseStr.c_str(),
- !PersistentConn_, !Digest_.empty());
+ Reader_ = new httpAgentReader(*this, urlBaseStr.c_str(),
+ !PersistentConn_, !Digest_.empty());
- if (Reader_->readHeader()) {
+ if (Reader_->readHeader()) {
//mReader->getHeader()->Print();
- if (getHeader()->http_status == HTTP_UNAUTHORIZED &&
- step < 1 &&
- Digest_.processHeader(getAuthHeader(),
- urlStr.c_str(),
- "GET")) {
+ if (getHeader()->http_status == HTTP_UNAUTHORIZED &&
+ step < 1 &&
+ Digest_.processHeader(getAuthHeader(),
+ urlStr.c_str(),
+ "GET")) {
//mReader->skipTheRest();
- delete Reader_;
+ delete Reader_;
Reader_ = nullptr;
- ErrCode_ = 0;
+ ErrCode_ = 0;
Disconnect();
continue;
}
@@ -365,7 +365,7 @@ bool httpLoadAgent::doStartRequest() {
return false;
}
- ErrCode_ = HTTP_UNAUTHORIZED;
+ ErrCode_ = HTTP_UNAUTHORIZED;
return false;
}
diff --git a/library/cpp/http/fetch/httpload.h b/library/cpp/http/fetch/httpload.h
index 5fc03d4be8..e22e4b809e 100644
--- a/library/cpp/http/fetch/httpload.h
+++ b/library/cpp/http/fetch/httpload.h
@@ -1,9 +1,9 @@
#pragma once
-#include "httpagent.h"
-#include "httpparser.h"
-#include "http_digest.h"
-
+#include "httpagent.h"
+#include "httpparser.h"
+#include "http_digest.h"
+
#include <util/system/compat.h>
#include <util/string/vector.h>
#include <util/network/ip.h>
@@ -20,7 +20,7 @@
/********************************************************/
// This class is used as a base one for flexible
// socket handling
-class socketAbstractHandler {
+class socketAbstractHandler {
public:
virtual bool Good() = 0;
@@ -36,12 +36,12 @@ public:
virtual ssize_t read(void* buffer, ssize_t buflen) = 0;
- virtual ~socketAbstractHandler() {
- }
+ virtual ~socketAbstractHandler() {
+ }
protected:
- socketAbstractHandler() {
- }
+ socketAbstractHandler() {
+ }
};
/********************************************************/
@@ -49,54 +49,54 @@ protected:
// socketAbstractHandler
// (it is used by template scheme,
// so it does not have virtual methods)
-class TSocketHandlerPtr {
+class TSocketHandlerPtr {
protected:
- socketAbstractHandler* Handler_;
+ socketAbstractHandler* Handler_;
public:
- TSocketHandlerPtr()
- : Handler_(nullptr)
- {
- }
+ TSocketHandlerPtr()
+ : Handler_(nullptr)
+ {
+ }
- virtual ~TSocketHandlerPtr() {
- delete Handler_;
- }
+ virtual ~TSocketHandlerPtr() {
+ delete Handler_;
+ }
- int Good() {
- return (Handler_ && Handler_->Good());
- }
+ int Good() {
+ return (Handler_ && Handler_->Good());
+ }
- int Connect(const TAddrList& addrs, TDuration Timeout) {
- return (Handler_) ? Handler_->Connect(addrs, Timeout) : 1;
+ int Connect(const TAddrList& addrs, TDuration Timeout) {
+ return (Handler_) ? Handler_->Connect(addrs, Timeout) : 1;
}
- void Disconnect() {
- if (Handler_)
- Handler_->Disconnect();
+ void Disconnect() {
+ if (Handler_)
+ Handler_->Disconnect();
}
- void shutdown() {
- if (Handler_)
- Handler_->shutdown();
+ void shutdown() {
+ if (Handler_)
+ Handler_->shutdown();
}
- bool send(const char* message, ssize_t messlen) {
- return (Handler_) ? Handler_->send(message, messlen) : false;
+ bool send(const char* message, ssize_t messlen) {
+ return (Handler_) ? Handler_->send(message, messlen) : false;
}
- virtual bool peek() {
- return (Handler_) ? Handler_->peek() : false;
+ virtual bool peek() {
+ return (Handler_) ? Handler_->peek() : false;
}
- virtual ssize_t read(void* buffer, ssize_t buflen) {
- return (Handler_) ? Handler_->read(buffer, buflen) : 0;
+ virtual ssize_t read(void* buffer, ssize_t buflen) {
+ return (Handler_) ? Handler_->read(buffer, buflen) : 0;
}
- void setHandler(socketAbstractHandler* handler) {
- if (Handler_)
- delete Handler_;
- Handler_ = handler;
+ void setHandler(socketAbstractHandler* handler) {
+ if (Handler_)
+ delete Handler_;
+ Handler_ = handler;
}
};
@@ -108,58 +108,58 @@ using httpSpecialAgent = THttpAgent<TSocketHandlerPtr>;
/********************************************************/
// Regular handler is used as implementation of
// socketAbstractHandler for work through HTTP protocol
-class socketRegularHandler: public socketAbstractHandler {
-protected:
- TSimpleSocketHandler Socket_;
+class socketRegularHandler: public socketAbstractHandler {
+protected:
+ TSimpleSocketHandler Socket_;
-public:
- socketRegularHandler()
- : Socket_()
- {
- }
+public:
+ socketRegularHandler()
+ : Socket_()
+ {
+ }
- bool Good() override {
- return Socket_.Good();
+ bool Good() override {
+ return Socket_.Good();
}
- int Connect(const TAddrList& addrs, TDuration Timeout) override {
+ int Connect(const TAddrList& addrs, TDuration Timeout) override {
return Socket_.Connect(addrs, Timeout);
}
- void Disconnect() override {
- Socket_.Disconnect();
+ void Disconnect() override {
+ Socket_.Disconnect();
}
- void shutdown() override {
+ void shutdown() override {
//Do not block writing to socket
//There are servers that works in a bad way with this
//mSocket.shutdown();
}
- bool send(const char* message, ssize_t messlen) override {
- return Socket_.send(message, messlen);
+ bool send(const char* message, ssize_t messlen) override {
+ return Socket_.send(message, messlen);
}
- bool peek() override {
- return Socket_.peek();
+ bool peek() override {
+ return Socket_.peek();
}
- ssize_t read(void* buffer, ssize_t buflen) override {
- return Socket_.read(buffer, buflen);
+ ssize_t read(void* buffer, ssize_t buflen) override {
+ return Socket_.read(buffer, buflen);
}
};
/********************************************************/
// The base factory that allows to choose an appropriate
// socketAbstractHandler implementation by url schema
-
-class socketHandlerFactory {
-public:
- virtual ~socketHandlerFactory() {
- }
+
+class socketHandlerFactory {
+public:
+ virtual ~socketHandlerFactory() {
+ }
//returns mHandler_HTTP for correct HTTP-based url
- virtual socketAbstractHandler* chooseHandler(const THttpURL& url);
+ virtual socketAbstractHandler* chooseHandler(const THttpURL& url);
static socketHandlerFactory sInstance;
};
@@ -168,138 +168,138 @@ public:
// Section 2: the configurates tool to parse an HTTP-response
/********************************************************/
-class httpAgentReader: public THttpParserGeneric<1> {
-protected:
- THttpAuthHeader Header_;
- httpSpecialAgent& Agent_;
+class httpAgentReader: public THttpParserGeneric<1> {
+protected:
+ THttpAuthHeader Header_;
+ httpSpecialAgent& Agent_;
- char* Buffer_;
- void* BufPtr_;
- int BufSize_;
- long BufRest_;
+ char* Buffer_;
+ void* BufPtr_;
+ int BufSize_;
+ long BufRest_;
void readBuf();
- bool step() {
- if (BufRest_ == 0)
+ bool step() {
+ if (BufRest_ == 0)
readBuf();
if (eof())
return false;
return true;
}
-public:
- httpAgentReader(httpSpecialAgent& agent,
- const char* baseUrl,
- bool assumeConnectionClosed,
- bool use_auth = false,
- int bufSize = 0x1000);
+public:
+ httpAgentReader(httpSpecialAgent& agent,
+ const char* baseUrl,
+ bool assumeConnectionClosed,
+ bool use_auth = false,
+ int bufSize = 0x1000);
~httpAgentReader();
- bool eof() {
- return BufRest_ < 0;
+ bool eof() {
+ return BufRest_ < 0;
}
- int error() {
- return Header_.error;
+ int error() {
+ return Header_.error;
}
- void setError(int errCode) {
- Header_.error = errCode;
+ void setError(int errCode) {
+ Header_.error = errCode;
}
- const THttpAuthHeader* getAuthHeader() {
- return &Header_;
+ const THttpAuthHeader* getAuthHeader() {
+ return &Header_;
}
- const THttpHeader* readHeader();
- long readPortion(void*& buf);
- bool skipTheRest();
+ const THttpHeader* readHeader();
+ long readPortion(void*& buf);
+ bool skipTheRest();
};
/********************************************************/
// Section 3: the main class
/********************************************************/
-class httpLoadAgent: public httpSpecialAgent {
-protected:
- socketHandlerFactory& Factory_;
- bool HandleAuthorization_;
- THttpURL URL_;
- bool PersistentConn_;
- httpAgentReader* Reader_;
- TVector<TString> Headers_;
- int ErrCode_;
- char* RealHost_;
- httpDigestHandler Digest_;
+class httpLoadAgent: public httpSpecialAgent {
+protected:
+ socketHandlerFactory& Factory_;
+ bool HandleAuthorization_;
+ THttpURL URL_;
+ bool PersistentConn_;
+ httpAgentReader* Reader_;
+ TVector<TString> Headers_;
+ int ErrCode_;
+ char* RealHost_;
+ httpDigestHandler Digest_;
void clearReader();
bool doSetHost(const TAddrList& addrs);
bool doStartRequest();
-public:
- httpLoadAgent(bool handleAuthorization = false,
- socketHandlerFactory& factory = socketHandlerFactory::sInstance);
+public:
+ httpLoadAgent(bool handleAuthorization = false,
+ socketHandlerFactory& factory = socketHandlerFactory::sInstance);
~httpLoadAgent();
void setRealHost(const char* host);
- void setIMS(const char* ifModifiedSince);
+ void setIMS(const char* ifModifiedSince);
void addHeaderInstruction(const char* instr);
void dropHeaderInstructions();
bool startRequest(const char* url,
const char* url_to_merge = nullptr,
- bool persistent = false,
+ bool persistent = false,
const TAddrList& addrs = TAddrList());
// deprecated v4-only
bool startRequest(const char* url,
const char* url_to_merge,
- bool persistent,
- ui32 ip);
+ bool persistent,
+ ui32 ip);
bool startRequest(const THttpURL& url,
- bool persistent = false,
+ bool persistent = false,
const TAddrList& addrs = TAddrList());
- bool setHost(const char* host_url,
- const TAddrList& addrs = TAddrList());
+ bool setHost(const char* host_url,
+ const TAddrList& addrs = TAddrList());
bool startOneRequest(const char* local_url);
- const THttpAuthHeader* getAuthHeader() {
- if (Reader_ && Reader_->getAuthHeader()->use_auth)
- return Reader_->getAuthHeader();
+ const THttpAuthHeader* getAuthHeader() {
+ if (Reader_ && Reader_->getAuthHeader()->use_auth)
+ return Reader_->getAuthHeader();
return nullptr;
}
- const THttpHeader* getHeader() {
- if (Reader_)
- return Reader_->getAuthHeader();
+ const THttpHeader* getHeader() {
+ if (Reader_)
+ return Reader_->getAuthHeader();
return nullptr;
}
- const THttpURL& getURL() {
- return URL_;
+ const THttpURL& getURL() {
+ return URL_;
}
- bool eof() {
- if (Reader_)
- return Reader_->eof();
+ bool eof() {
+ if (Reader_)
+ return Reader_->eof();
return true;
}
- int error() {
- if (ErrCode_)
- return ErrCode_;
- if (Reader_)
- return Reader_->error();
+ int error() {
+ if (ErrCode_)
+ return ErrCode_;
+ if (Reader_)
+ return Reader_->error();
return HTTP_BAD_URL;
}
- long readPortion(void*& buf) {
- if (Reader_)
- return Reader_->readPortion(buf);
+ long readPortion(void*& buf) {
+ if (Reader_)
+ return Reader_->readPortion(buf);
return -1;
}
};
diff --git a/library/cpp/http/fetch/httpparser.h b/library/cpp/http/fetch/httpparser.h
index 989409bdd2..769828e4ae 100644
--- a/library/cpp/http/fetch/httpparser.h
+++ b/library/cpp/http/fetch/httpparser.h
@@ -6,22 +6,22 @@
#include <library/cpp/mime/types/mime.h>
#include <util/system/yassert.h>
#include <library/cpp/http/misc/httpcodes.h>
-
-template <size_t headermax = 100 << 10, size_t bodymax = 1 << 20>
+
+template <size_t headermax = 100 << 10, size_t bodymax = 1 << 20>
struct TFakeCheck {
- bool Check(THttpHeader* /*header*/) {
- return false;
- }
- void CheckDocPart(void* /*buf*/, size_t /*len*/, THttpHeader* /*header*/) {
- } //for every part of DocumentBody will be called
- void CheckEndDoc(THttpHeader* /*header*/) {
- }
- size_t GetMaxHeaderSize() {
- return headermax;
- }
- size_t GetMaxBodySize(THttpHeader*) {
- return bodymax;
- }
+ bool Check(THttpHeader* /*header*/) {
+ return false;
+ }
+ void CheckDocPart(void* /*buf*/, size_t /*len*/, THttpHeader* /*header*/) {
+ } //for every part of DocumentBody will be called
+ void CheckEndDoc(THttpHeader* /*header*/) {
+ }
+ size_t GetMaxHeaderSize() {
+ return headermax;
+ }
+ size_t GetMaxBodySize(THttpHeader*) {
+ return bodymax;
+ }
};
class THttpParserBase {
@@ -37,17 +37,17 @@ public:
hp_read_chunk
};
- States GetState() {
- return State;
- }
+ States GetState() {
+ return State;
+ }
- void setAssumeConnectionClosed(int value) {
+ void setAssumeConnectionClosed(int value) {
AssumeConnectionClosed = value;
}
- THttpHeader* GetHttpHeader() const {
- return Header;
- }
+ THttpHeader* GetHttpHeader() const {
+ return Header;
+ }
protected:
int CheckHeaders() {
@@ -69,8 +69,8 @@ protected:
if (Header->compression_method != HTTP_COMPRESSION_UNSET &&
Header->compression_method != HTTP_COMPRESSION_IDENTITY &&
Header->compression_method != HTTP_COMPRESSION_GZIP &&
- Header->compression_method != HTTP_COMPRESSION_DEFLATE)
- {
+ Header->compression_method != HTTP_COMPRESSION_DEFLATE)
+ {
Header->error = HTTP_BAD_CONTENT_ENCODING;
return 1;
}
@@ -78,7 +78,7 @@ protected:
if (Header->connection_closed == -1)
Header->connection_closed = (Header->http_minor == 0 ||
AssumeConnectionClosed);
- if (!Header->transfer_chunked && !Header->connection_closed && Header->content_length < 0 && !HeadRequest) {
+ if (!Header->transfer_chunked && !Header->connection_closed && Header->content_length < 0 && !HeadRequest) {
Header->error = HTTP_LENGTH_UNKNOWN;
return 1;
}
@@ -93,15 +93,15 @@ protected:
THttpChunkParser ChunkParser;
States State;
long ChunkSize;
- THttpHeader* Header;
+ THttpHeader* Header;
int AssumeConnectionClosed;
bool HeadRequest;
};
-template <int isReader, typename TCheck = TFakeCheck<>>
+template <int isReader, typename TCheck = TFakeCheck<>>
class THttpParserGeneric: public THttpParserBase, public TCheck {
protected:
- long ParseGeneric(void*& buf, long& size) {
+ long ParseGeneric(void*& buf, long& size) {
if (!size) {
switch (State) {
case hp_error:
@@ -155,10 +155,10 @@ protected:
size -= long(HeaderParser.lastchar - (char*)buf + 1);
buf = HeaderParser.lastchar + 1;
State = CheckHeaders() ? hp_error
- : Header->transfer_chunked ? hp_begin_chunk_header
- : Header->content_length == 0 ? hp_eof
- : Header->content_length > 0 ? hp_read_alive
- : hp_read_closed;
+ : Header->transfer_chunked ? hp_begin_chunk_header
+ : Header->content_length == 0 ? hp_eof
+ : Header->content_length > 0 ? hp_read_alive
+ : hp_read_closed;
if (State == hp_begin_chunk_header) {
// unget \n for chunk reader
buf = (char*)buf - 1;
@@ -239,11 +239,11 @@ protected:
}
};
-template <class TCheck = TFakeCheck<>>
+template <class TCheck = TFakeCheck<>>
class THttpParser: public THttpParserGeneric<0, TCheck> {
typedef THttpParserGeneric<0, TCheck> TBaseT; //sorry avoiding gcc 3.4.6 BUG!
public:
- void Init(THttpHeader* H, bool head_request = false) {
+ void Init(THttpHeader* H, bool head_request = false) {
TBaseT::Header = H;
TBaseT::HeaderParser.Init(TBaseT::Header);
TBaseT::State = TBaseT::hp_in_header;
@@ -251,19 +251,19 @@ public:
TBaseT::HeadRequest = head_request;
}
- void Parse(void* buf, long size) {
+ void Parse(void* buf, long size) {
TBaseT::ParseGeneric(buf, size);
}
};
class TMemoReader {
public:
- int Init(void* buf, long bufsize) {
+ int Init(void* buf, long bufsize) {
Buf = buf;
Bufsize = bufsize;
return 0;
}
- long Read(void*& buf) {
+ long Read(void*& buf) {
Y_ASSERT(Bufsize >= 0);
if (!Bufsize) {
Bufsize = -1;
@@ -277,15 +277,15 @@ public:
protected:
long Bufsize;
- void* Buf;
+ void* Buf;
};
template <class Reader>
class THttpReader: public THttpParserGeneric<1>, public Reader {
typedef THttpParserGeneric<1> TBaseT;
-
+
public:
- using TBaseT::AssumeConnectionClosed;
+ using TBaseT::AssumeConnectionClosed;
using TBaseT::Header;
using TBaseT::ParseGeneric;
using TBaseT::State;
@@ -299,7 +299,7 @@ public:
return parsHeader ? ParseHeader() : SkipHeader();
}
- long Read(void*& buf) {
+ long Read(void*& buf) {
long Chunk;
do {
if (!Size) {
@@ -317,7 +317,7 @@ public:
if (State == hp_eof) {
Size = 0;
Eoferr = 0;
- } else if (State == hp_error)
+ } else if (State == hp_error)
return Eoferr = -1;
} while (!Chunk);
return Chunk;
@@ -352,9 +352,9 @@ protected:
hdrsize -= Size;
}
State = Header->transfer_chunked ? hp_begin_chunk_header
- : Header->content_length == 0 ? hp_eof
- : Header->content_length > 0 ? hp_read_alive
- : hp_read_closed;
+ : Header->content_length == 0 ? hp_eof
+ : Header->content_length > 0 ? hp_read_alive
+ : hp_read_closed;
Header->entity_size = 0;
if (State == hp_eof)
Eoferr = 0;
@@ -366,7 +366,7 @@ protected:
return 0;
}
- void* Ptr;
+ void* Ptr;
long Size;
- int Eoferr;
+ int Eoferr;
};
diff --git a/library/cpp/http/fetch/httpparser_ut.cpp b/library/cpp/http/fetch/httpparser_ut.cpp
index 6957eb2f5f..3b3b938e7a 100644
--- a/library/cpp/http/fetch/httpparser_ut.cpp
+++ b/library/cpp/http/fetch/httpparser_ut.cpp
@@ -2,13 +2,13 @@
#include <library/cpp/testing/unittest/registar.h>
-#define ENUM_OUT(arg) \
- case type ::arg: { \
- out << #arg; \
- return; \
- }
+#define ENUM_OUT(arg) \
+ case type ::arg: { \
+ out << #arg; \
+ return; \
+ }
-template <>
+template <>
void Out<THttpParserBase::States>(IOutputStream& out, THttpParserBase::States st) {
using type = THttpParserBase::States;
switch (st) {
@@ -24,27 +24,27 @@ void Out<THttpParserBase::States>(IOutputStream& out, THttpParserBase::States st
}
namespace {
- class TSomethingLikeFakeCheck;
+ class TSomethingLikeFakeCheck;
- using TTestHttpParser = THttpParser<TSomethingLikeFakeCheck>;
+ using TTestHttpParser = THttpParser<TSomethingLikeFakeCheck>;
- class TSomethingLikeFakeCheck {
- TString Body_;
+ class TSomethingLikeFakeCheck {
+ TString Body_;
- public:
- const TString& Body() const {
- return Body_;
- }
+ public:
+ const TString& Body() const {
+ return Body_;
+ }
- // other functions are not really called by THttpParser
- void CheckDocPart(const void* buf, size_t len, THttpHeader* /* header */) {
- TString s(static_cast<const char*>(buf), len);
- Cout << "State = " << static_cast<TTestHttpParser*>(this)->GetState() << ", CheckDocPart(" << s.Quote() << ")\n";
- Body_ += s;
- }
- };
+ // other functions are not really called by THttpParser
+ void CheckDocPart(const void* buf, size_t len, THttpHeader* /* header */) {
+ TString s(static_cast<const char*>(buf), len);
+ Cout << "State = " << static_cast<TTestHttpParser*>(this)->GetState() << ", CheckDocPart(" << s.Quote() << ")\n";
+ Body_ += s;
+ }
+ };
-}
+}
Y_UNIT_TEST_SUITE(TestHttpParser) {
Y_UNIT_TEST(TestTrivialRequest) {
@@ -73,9 +73,9 @@ Y_UNIT_TEST_SUITE(TestHttpParser) {
UNIT_ASSERT_EQUAL(parser.GetState(), parser.hp_eof);
UNIT_ASSERT_EQUAL(parser.Body(), "OK");
UNIT_ASSERT_EQUAL(hdr.header_size, strlen(
- "HTTP/1.1 200 Ok\r\n"
- "Content-Length: 2\r\n"
- "\r\n"));
+ "HTTP/1.1 200 Ok\r\n"
+ "Content-Length: 2\r\n"
+ "\r\n"));
UNIT_ASSERT_EQUAL(hdr.entity_size, strlen("OK"));
}
@@ -98,36 +98,36 @@ Y_UNIT_TEST_SUITE(TestHttpParser) {
UNIT_ASSERT_EQUAL(parser.GetState(), parser.hp_eof);
UNIT_ASSERT_EQUAL(parser.Body(), "OkAllRight");
UNIT_ASSERT_EQUAL(hdr.header_size, strlen(
- "HTTP/1.1 200 OK\r\n"
- "Transfer-Encoding: chunked\r\n"
- "\r\n"));
+ "HTTP/1.1 200 OK\r\n"
+ "Transfer-Encoding: chunked\r\n"
+ "\r\n"));
const int off_by_one_err = -1; // XXX: it really looks so
UNIT_ASSERT_EQUAL(hdr.entity_size + off_by_one_err, strlen(
- "2\r\n"
- "Ok\r\n"
- "8\r\n"
- "AllRight\r\n"
- "0\r\n"
- "\r\n"));
+ "2\r\n"
+ "Ok\r\n"
+ "8\r\n"
+ "AllRight\r\n"
+ "0\r\n"
+ "\r\n"));
}
static const TString PipelineClenBlob_{
- "HTTP/1.1 200 Ok\r\n"
- "Content-Length: 4\r\n"
- "\r\n"
- "OK\r\n"
- "HTTP/1.1 200 Zz\r\n"
- "Content-Length: 4\r\n"
- "\r\n"
- "ZZ\r\n"};
-
- void AssertPipelineClen(TTestHttpParser & parser, const THttpHeader& hdr) {
+ "HTTP/1.1 200 Ok\r\n"
+ "Content-Length: 4\r\n"
+ "\r\n"
+ "OK\r\n"
+ "HTTP/1.1 200 Zz\r\n"
+ "Content-Length: 4\r\n"
+ "\r\n"
+ "ZZ\r\n"};
+
+ void AssertPipelineClen(TTestHttpParser & parser, const THttpHeader& hdr) {
UNIT_ASSERT_EQUAL(parser.GetState(), parser.hp_eof);
UNIT_ASSERT_EQUAL(4, hdr.content_length);
UNIT_ASSERT_EQUAL(hdr.header_size, strlen(
- "HTTP/1.1 200 Ok\r\n"
- "Content-Length: 4\r\n"
- "\r\n"));
+ "HTTP/1.1 200 Ok\r\n"
+ "Content-Length: 4\r\n"
+ "\r\n"));
}
Y_UNIT_TEST(TestPipelineClenByteByByte) {
@@ -154,55 +154,55 @@ Y_UNIT_TEST_SUITE(TestHttpParser) {
parser.Parse((void*)blob.data(), blob.size());
AssertPipelineClen(parser, hdr);
UNIT_ASSERT_EQUAL(parser.Body(),
- "OK\r\n"
- "HTTP/1.1 200 Zz\r\n"
- "Content-Length: 4\r\n"
- "\r\n"
- "ZZ\r\n");
+ "OK\r\n"
+ "HTTP/1.1 200 Zz\r\n"
+ "Content-Length: 4\r\n"
+ "\r\n"
+ "ZZ\r\n");
UNIT_ASSERT_EQUAL(hdr.entity_size, strlen(
- "OK\r\n"
- "HTTP/1.1 200 Zz\r\n"
- "Content-Length: 4\r\n"
- "\r\n"
- "ZZ\r\n"));
+ "OK\r\n"
+ "HTTP/1.1 200 Zz\r\n"
+ "Content-Length: 4\r\n"
+ "\r\n"
+ "ZZ\r\n"));
}
static const TString PipelineChunkedBlob_{
- "HTTP/1.1 200 OK\r\n"
- "Transfer-Encoding: chunked\r\n"
- "\r\n"
- "2\r\n"
- "Ok\r\n"
- "8\r\n"
- "AllRight\r\n"
- "0\r\n"
- "\r\n"
- "HTTP/1.1 200 OK\r\n"
- "Transfer-Encoding: chunked\r\n"
- "\r\n"
- "2\r\n"
- "Yo\r\n"
- "8\r\n"
- "uWin!Iam\r\n"
- "0\r\n"
- "\r\n"};
-
- void AssertPipelineChunked(TTestHttpParser & parser, const THttpHeader& hdr) {
+ "HTTP/1.1 200 OK\r\n"
+ "Transfer-Encoding: chunked\r\n"
+ "\r\n"
+ "2\r\n"
+ "Ok\r\n"
+ "8\r\n"
+ "AllRight\r\n"
+ "0\r\n"
+ "\r\n"
+ "HTTP/1.1 200 OK\r\n"
+ "Transfer-Encoding: chunked\r\n"
+ "\r\n"
+ "2\r\n"
+ "Yo\r\n"
+ "8\r\n"
+ "uWin!Iam\r\n"
+ "0\r\n"
+ "\r\n"};
+
+ void AssertPipelineChunked(TTestHttpParser & parser, const THttpHeader& hdr) {
UNIT_ASSERT_EQUAL(parser.GetState(), parser.hp_eof);
UNIT_ASSERT_EQUAL(parser.Body(), "OkAllRight");
UNIT_ASSERT_EQUAL(-1, hdr.content_length);
UNIT_ASSERT_EQUAL(hdr.header_size, strlen(
- "HTTP/1.1 200 OK\r\n"
- "Transfer-Encoding: chunked\r\n"
- "\r\n"));
+ "HTTP/1.1 200 OK\r\n"
+ "Transfer-Encoding: chunked\r\n"
+ "\r\n"));
const int off_by_one_err = -1;
UNIT_ASSERT_EQUAL(hdr.entity_size + off_by_one_err, strlen(
- "2\r\n"
- "Ok\r\n"
- "8\r\n"
- "AllRight\r\n"
- "0\r\n"
- "\r\n"));
+ "2\r\n"
+ "Ok\r\n"
+ "8\r\n"
+ "AllRight\r\n"
+ "0\r\n"
+ "\r\n"));
}
Y_UNIT_TEST(TestPipelineChunkedByteByByte) {
diff --git a/library/cpp/http/fetch/httpzreader.h b/library/cpp/http/fetch/httpzreader.h
index a8df608a9f..68eb00853d 100644
--- a/library/cpp/http/fetch/httpzreader.h
+++ b/library/cpp/http/fetch/httpzreader.h
@@ -1,26 +1,26 @@
#pragma once
-#include "httpheader.h"
-#include "httpparser.h"
-#include "exthttpcodes.h"
+#include "httpheader.h"
+#include "httpparser.h"
+#include "exthttpcodes.h"
#include <util/system/defaults.h>
#include <util/generic/yexception.h>
#include <contrib/libs/zlib/zlib.h>
-#include <errno.h>
-
+#include <errno.h>
+
#ifndef ENOTSUP
-#define ENOTSUP 45
+#define ENOTSUP 45
#endif
template <class Reader>
class TCompressedHttpReader: public THttpReader<Reader> {
typedef THttpReader<Reader> TBase;
-
+
public:
- using TBase::AssumeConnectionClosed;
+ using TBase::AssumeConnectionClosed;
using TBase::Header;
using TBase::ParseGeneric;
using TBase::State;
@@ -78,7 +78,7 @@ public:
return ret;
}
- long Read(void*& buf) {
+ long Read(void*& buf) {
if (!CompressedInput) {
long res = TBase::Read(buf);
if (res > 0) {
@@ -93,7 +93,7 @@ public:
while (true) {
if (Stream.avail_in == 0) {
- void* tmpin = Stream.next_in;
+ void* tmpin = Stream.next_in;
long res = TBase::Read(tmpin);
Stream.next_in = (Bytef*)tmpin;
if (res <= 0)
@@ -121,10 +121,10 @@ public:
ZErr = E2BIG;
return -1;
}
- if (!IgnoreTrailingGarbage && BufSize == Stream.avail_out && Stream.avail_in > 0) {
+ if (!IgnoreTrailingGarbage && BufSize == Stream.avail_out && Stream.avail_in > 0) {
Header->error = EXT_HTTP_GZIPERROR;
ZErr = EFAULT;
- Stream.msg = (char*)"trailing garbage";
+ Stream.msg = (char*)"trailing garbage";
return -1;
}
return long(BufSize - Stream.avail_out);
@@ -148,7 +148,7 @@ public:
return -1;
}
- const char* ZMsg() const {
+ const char* ZMsg() const {
return Stream.msg;
}
@@ -173,7 +173,7 @@ protected:
return 0;
case HTTP_COMPRESSION_GZIP:
CompressedInput = true;
- winsize += 16; // 16 indicates gzip, see zlib.h
+ winsize += 16; // 16 indicates gzip, see zlib.h
break;
case HTTP_COMPRESSION_DEFLATE:
CompressedInput = true;
@@ -240,21 +240,21 @@ protected:
bool IgnoreTrailingGarbage;
};
-class zlib_exception: public yexception {
+class zlib_exception: public yexception {
};
template <class Reader>
class SCompressedHttpReader: public TCompressedHttpReader<Reader> {
typedef TCompressedHttpReader<Reader> TBase;
-
+
public:
using TBase::ZError;
using TBase::ZMsg;
SCompressedHttpReader()
- : TBase()
- {
- }
+ : TBase()
+ {
+ }
int Init(
THttpHeader* H,
@@ -268,7 +268,7 @@ public:
return (int)HandleRetValue((long)ret);
}
- long Read(void*& buf) {
+ long Read(void*& buf) {
long ret = TBase::Read(buf);
return HandleRetValue(ret);
}
@@ -281,7 +281,7 @@ protected:
case ENOMEM:
ythrow yexception() << "SCompressedHttpReader: not enough memory";
case EINVAL:
- ythrow yexception() << "SCompressedHttpReader: zlib error: " << ZMsg();
+ ythrow yexception() << "SCompressedHttpReader: zlib error: " << ZMsg();
case ENOTSUP:
ythrow yexception() << "SCompressedHttpReader: unsupported compression method";
case EFAULT:
diff --git a/library/cpp/http/fetch/library-htfetch_ut_hreflang_in.h b/library/cpp/http/fetch/library-htfetch_ut_hreflang_in.h
index d01a5911e7..0df89bdc79 100644
--- a/library/cpp/http/fetch/library-htfetch_ut_hreflang_in.h
+++ b/library/cpp/http/fetch/library-htfetch_ut_hreflang_in.h
@@ -1,155 +1,155 @@
#pragma once
char hreflang_ut_in[] = "HTTP/1.1 200 OK\n"
- "Date: Thu, 15 Nov 2012 22:38:28 GMT\n"
- "Server: Apache/2\n"
- "X-Powered-By: PHP/5.2.17\n"
- "Set-Cookie: PHPSESSID=6d69474d1cc019d7d82714c9472bc6d6; path=/\n"
- "Expires: Thu, 19 Nov 1981 08:52:00 GMT\n"
- "Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0\n"
- "Pragma: no-cache\n"
- "Link: <http://www.forexticket.cn.com/zh/currency/converter-EEK-XAG>; rel='alternate'; hreflang='zh-CN'\n"
- "Link: <http://www.forexticket.tw/zh/currency/converter-EEK-XAG>; rel='alternate'; hreflang='zh-TW'\n"
- "Link: <http://www.forexticket.hk/zh/currency/converter-EEK-XAG>; rel='alternate'; hreflang='zh-HK'\n"
- "Link: <http://www.forexticket.sg/zh/currency/converter-EEK-XAG>; rel='alternate'; hreflang='zh-SG'\n"
- "Link: <http://www.forexticket.in/hi/currency/converter-EEK-XAG>; rel='alternate'; hreflang='hi-IN'\n"
- "Link: <http://www.forexticket.com.fj/hi/currency/converter-EEK-XAG>; rel='alternate'; hreflang='hi-FJ'\n"
- "Link: <http://www.forexticket.in/en/currency/converter-EEK-XAG>; rel='alternate'; hreflang='en-IN'\n"
- "Link: <http://www.forexticket.us/en/currency/converter-EEK-XAG>; rel='alternate'; hreflang='en-US'\n"
- "Link: <http://www.forexticket.com.pk/en/currency/converter-EEK-XAG>; rel='alternate'; hreflang='en-PK'\n"
- "Link: <http://www.forexticket-bd.com/en/currency/converter-EEK-XAG>; rel='alternate'; hreflang='en-BD'\n"
- "Link: <http://www.forexticket-ng.com/en/currency/converter-EEK-XAG>; rel='alternate'; hreflang='en-NG'\n"
- "Link: <http://www.forexticket.co.uk/en/currency/converter-EEK-XAG>; rel='alternate'; hreflang='en-GB'\n"
- "Link: <http://www.forexticket.co.za/en/currency/converter-EEK-XAG>; rel='alternate'; hreflang='en-ZA'\n"
- "Link: <http://www.forexticket.co.ke/en/currency/converter-EEK-XAG>; rel='alternate'; hreflang='en-KE'\n"
- "Link: <http://www.forexticket.com/en/currency/converter-EEK-XAG>; rel='alternate'; hreflang='en-CA'\n"
- "Link: <http://www.forexticket-gh.com/en/currency/converter-EEK-XAG>; rel='alternate'; hreflang='en-GH'\n"
- "Link: <http://www.forexticket.biz/en/currency/converter-EEK-XAG>; rel='alternate'; hreflang='en-AU'\n"
- "Link: <http://www.forexticket.cm/en/currency/converter-EEK-XAG>; rel='alternate'; hreflang='en-CM'\n"
- "Link: <http://www.forexticket-kh.com/en/currency/converter-EEK-XAG>; rel='alternate'; hreflang='en-KH'\n"
- "Link: <http://www.forexticket.hk/en/currency/converter-EEK-XAG>; rel='alternate'; hreflang='en-HK'\n"
- "Link: <http://www.forexticket.la/en/currency/converter-EEK-XAG>; rel='alternate'; hreflang='en-LA'\n"
- "Link: <http://www.forexticket.sg/en/currency/converter-EEK-XAG>; rel='alternate'; hreflang='en-SG'\n"
- "Link: <http://www.forexticket.co.nz/en/currency/converter-EEK-XAG>; rel='alternate'; hreflang='en-NZ'\n"
- "Link: <http://www.forexticket.com.pr/en/currency/converter-EEK-XAG>; rel='alternate'; hreflang='en-PR'\n"
- "Link: <http://www.forexticket.com.fj/en/currency/converter-EEK-XAG>; rel='alternate'; hreflang='en-FJ'\n"
- "Link: <http://www.forexticket.us/es/cambio/divisas-EEK-XAG>; rel='alternate'; hreflang='es-US'\n"
- "Link: <http://www.forexticket.mx/es/cambio/divisas-EEK-XAG>; rel='alternate'; hreflang='es-MX'\n"
- "Link: <http://www.forexticket.co/es/cambio/divisas-EEK-XAG>; rel='alternate'; hreflang='es-CO'\n"
- "Link: <http://www.forexticket.com.ar/es/cambio/divisas-EEK-XAG>; rel='alternate'; hreflang='es-AR'\n"
- "Link: <http://www.forexticket-pe.com/es/cambio/divisas-EEK-XAG>; rel='alternate'; hreflang='es-PE'\n"
- "Link: <http://www.forexticket.co.ve/es/cambio/divisas-EEK-XAG>; rel='alternate'; hreflang='es-VE'\n"
- "Link: <http://www.forexticket.cl/es/cambio/divisas-EEK-XAG>; rel='alternate'; hreflang='es-CL'\n"
- "Link: <http://www.forexticket.ec/es/cambio/divisas-EEK-XAG>; rel='alternate'; hreflang='es-EC'\n"
- "Link: <http://www.forexticket.com.gt/es/cambio/divisas-EEK-XAG>; rel='alternate'; hreflang='es-GT'\n"
- "Link: <http://www.forexticket.bo/es/cambio/divisas-EEK-XAG>; rel='alternate'; hreflang='es-BO'\n"
- "Link: <http://www.forexticket.hn/es/cambio/divisas-EEK-XAG>; rel='alternate'; hreflang='es-HN'\n"
- "Link: <http://www.forexticket.com.py/es/cambio/divisas-EEK-XAG>; rel='alternate'; hreflang='es-PY'\n"
- "Link: <http://www.forexticket.es/es/cambio/divisas-EEK-XAG>; rel='alternate'; hreflang='es-ES'\n"
- "Link: <http://www.forexticket.com.sv/es/cambio/divisas-EEK-XAG>; rel='alternate'; hreflang='es-SV'\n"
- "Link: <http://www.forexticket.com.ni/es/cambio/divisas-EEK-XAG>; rel='alternate'; hreflang='es-NI'\n"
- "Link: <http://www.forexticket.co.cr/es/cambio/divisas-EEK-XAG>; rel='alternate'; hreflang='es-CR'\n"
- "Link: <http://www.forexticket.com.pr/es/cambio/divisas-EEK-XAG>; rel='alternate'; hreflang='es-PR'\n"
- "Link: <http://www.forexticket.com.uy/es/cambio/divisas-EEK-XAG>; rel='alternate'; hreflang='es-UY'\n"
- "Link: <http://www.forexticket.com.pa/es/cambio/divisas-EEK-XAG>; rel='alternate'; hreflang='es-PA'\n"
- "Link: <http://www.forexticket.asia.com/id/currency/converter-EEK-XAG>; rel='alternate'; hreflang='id-ID'\n"
- "Link: <http://www.forexticket.com.br/pt/moeda/conversor-EEK-XAG>; rel='alternate'; hreflang='pt-BR'\n"
- "Link: <http://www.forexticket-mz.com/pt/moeda/conversor-EEK-XAG>; rel='alternate'; hreflang='pt-MZ'\n"
- "Link: <http://www.forexticket.com.pt/pt/moeda/conversor-EEK-XAG>; rel='alternate'; hreflang='pt-PT'\n"
- "Link: <http://www.forexticket.tl/pt/moeda/conversor-EEK-XAG>; rel='alternate'; hreflang='pt-TL'\n"
- "Link: <http://www.forexticket.ru/ru/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ru-RU'\n"
- "Link: <http://www.forexticket-kz.com/ru/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ru-KZ'\n"
- "Link: <http://www.forexticket-tj.com/ru/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ru-TJ'\n"
- "Link: <http://www.forexticket-kg.com/ru/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ru-KG'\n"
- "Link: <http://www.forexticket-ge.com/ru/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ru-GE'\n"
- "Link: <http://www.forexticket.mn/ru/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ru-MN'\n"
- "Link: <http://www.forexticket.jp/ja/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ja-JP'\n"
- "Link: <http://www.forexticket-ph.com/tl/currency/converter-EEK-XAG>; rel='alternate'; hreflang='tl-PH'\n"
- "Link: <http://www.forexticket.vn/vi/currency/converter-EEK-XAG>; rel='alternate'; hreflang='vi-VN'\n"
- "Link: <http://www.forexticket.de/de/waehrungsumrechner/devisen-EEK-XAG>; rel='alternate'; hreflang='de-DE'\n"
- "Link: <http://www.forexticket.be/de/waehrungsumrechner/devisen-EEK-XAG>; rel='alternate'; hreflang='de-BE'\n"
- "Link: <http://www.forexticket.at/de/waehrungsumrechner/devisen-EEK-XAG>; rel='alternate'; hreflang='de-AT'\n"
- "Link: <http://www.forexticket.ch/de/waehrungsumrechner/devisen-EEK-XAG>; rel='alternate'; hreflang='de-CH'\n"
- "Link: <http://www.forexticket.lu/de/waehrungsumrechner/devisen-EEK-XAG>; rel='alternate'; hreflang='de-LU'\n"
- "Link: <http://www.forexticket.li/de/waehrungsumrechner/devisen-EEK-XAG>; rel='alternate'; hreflang='de-LI'\n"
- "Link: <http://www.forexticket.de/de/waehrungsumrechner/devisen-EEK-XAG>; rel='canonical'\n"
- "Link: <http://www.forexticket-eg.com/ar/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ar-EG'\n"
- "Link: <http://www.forexticket-dz.com/ar/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ar-DZ'\n"
- "Link: <http://www.forexticket-ma.com/ar/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ar-MA'\n"
- "Link: <http://www.forexticket-iq.com/ar/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ar-IQ'\n"
- "Link: <http://www.forexticket-sa.com/ar/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ar-SA'\n"
- "Link: <http://www.forexticket-sy.com/ar/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ar-SY'\n"
- "Link: <http://www.forexticket-tn.com/ar/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ar-TN'\n"
- "Link: <http://www.forexticket-td.com/ar/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ar-TD'\n"
- "Link: <http://www.forexticket-so.com/ar/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ar-SO'\n"
- "Link: <http://www.forexticket.co.il/ar/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ar-IL'\n"
- "Link: <http://www.forexticket-jo.com/ar/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ar-JO'\n"
- "Link: <http://www.forexticket.ae/ar/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ar-AE'\n"
- "Link: <http://www.forexticket-lb.com/ar/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ar-LB'\n"
- "Link: <http://www.forexticket-om.com/ar/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ar-OM'\n"
- "Link: <http://www.forexticket-kw.com/ar/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ar-KW'\n"
- "Link: <http://www.forexticket-tr.com/tr/currency/converter-EEK-XAG>; rel='alternate'; hreflang='tr-TR'\n"
- "Link: <http://www.forexticket-bg.com/tr/currency/converter-EEK-XAG>; rel='alternate'; hreflang='tr-BG'\n"
- "Link: <http://www.forexticket-cy.com/tr/currency/converter-EEK-XAG>; rel='alternate'; hreflang='tr-CY'\n"
- "Link: <http://www.forexticket.ir/fa/currency/converter-EEK-XAG>; rel='alternate'; hreflang='fa-IR'\n"
- "Link: <http://www.forexticket.af/fa/currency/converter-EEK-XAG>; rel='alternate'; hreflang='fa-AF'\n"
- "Link: <http://www.forexticket.cd/fr/conversion/monnaie-EEK-XAG>; rel='alternate'; hreflang='fr-CD'\n"
- "Link: <http://www.forexticket.fr/fr/conversion/monnaie-EEK-XAG>; rel='alternate'; hreflang='fr-FR'\n"
- "Link: <http://www.forexticket.com/fr/conversion/monnaie-EEK-XAG>; rel='alternate'; hreflang='fr-CA'\n"
- "Link: <http://www.forexticket.mg/fr/conversion/monnaie-EEK-XAG>; rel='alternate'; hreflang='fr-MG'\n"
- "Link: <http://www.forexticket.cm/fr/conversion/monnaie-EEK-XAG>; rel='alternate'; hreflang='fr-CM'\n"
- "Link: <http://www.forexticket-kh.com/fr/conversion/monnaie-EEK-XAG>; rel='alternate'; hreflang='fr-KH'\n"
- "Link: <http://www.forexticket-ml.com/fr/conversion/monnaie-EEK-XAG>; rel='alternate'; hreflang='fr-ML'\n"
- "Link: <http://www.forexticket-sn.com/fr/conversion/monnaie-EEK-XAG>; rel='alternate'; hreflang='fr-SN'\n"
- "Link: <http://www.forexticket-tn.com/fr/conversion/monnaie-EEK-XAG>; rel='alternate'; hreflang='fr-TN'\n"
- "Link: <http://www.forexticket-td.com/fr/conversion/monnaie-EEK-XAG>; rel='alternate'; hreflang='fr-TD'\n"
- "Link: <http://www.forexticket.be/fr/conversion/monnaie-EEK-XAG>; rel='alternate'; hreflang='fr-BE'\n"
- "Link: <http://www.forexticket-gn.com/fr/conversion/monnaie-EEK-XAG>; rel='alternate'; hreflang='fr-GN'\n"
- "Link: <http://www.forexticket.ht/fr/conversion/monnaie-EEK-XAG>; rel='alternate'; hreflang='fr-HT'\n"
- "Link: <http://www.forexticket.ch/fr/conversion/monnaie-EEK-XAG>; rel='alternate'; hreflang='fr-CH'\n"
- "Link: <http://www.forexticket.la/fr/conversion/monnaie-EEK-XAG>; rel='alternate'; hreflang='fr-LA'\n"
- "Link: <http://www.forexticket.lu/fr/conversion/monnaie-EEK-XAG>; rel='alternate'; hreflang='fr-LU'\n"
- "Link: <http://www.forexticket-th.com/th/currency/converter-EEK-XAG>; rel='alternate'; hreflang='th-TH'\n"
- "Link: <http://www.forexticket.co.uk/cy/currency/converter-EEK-XAG>; rel='alternate'; hreflang='cy-GB'\n"
- "Link: <http://www.forexticket.co.uk/ga/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ga-GB'\n"
- "Link: <http://www.forexticket.it/it/convertitore/valuta-EEK-XAG>; rel='alternate'; hreflang='it-IT'\n"
- "Link: <http://www.forexticket.ch/it/convertitore/valuta-EEK-XAG>; rel='alternate'; hreflang='it-CH'\n"
- "Link: <http://www.forexticket.co.za/af/currency/converter-EEK-XAG>; rel='alternate'; hreflang='af-ZA'\n"
- "Link: <http://www.forexticket.kr/ko/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ko-KR'\n"
- "Link: <http://www.forexticket-ua.com/uk/currency/converter-EEK-XAG>; rel='alternate'; hreflang='uk-UA'\n"
- "Link: <http://www.forexticket-tz.com/sw/currency/converter-EEK-XAG>; rel='alternate'; hreflang='sw-TZ'\n"
- "Link: <http://www.forexticket.co.ke/sw/currency/converter-EEK-XAG>; rel='alternate'; hreflang='sw-KE'\n"
- "Link: <http://www.forexticket.pl/pl/currency/converter-EEK-XAG>; rel='alternate'; hreflang='pl-PL'\n"
- "Link: <http://www.forexticket.com.my/ms/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ms-MY'\n"
- "Link: <http://www.forexticket.sg/ms/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ms-SG'\n"
- "Link: <http://www.forexticket.ro/ro/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ro-RO'\n"
- "Link: <http://www.forexticket.nl/nl/currency/converter-EEK-XAG>; rel='alternate'; hreflang='nl-NL'\n"
- "Link: <http://www.forexticket.be/nl/currency/converter-EEK-XAG>; rel='alternate'; hreflang='nl-BE'\n"
- "Link: <http://www.forexticket.gr/el/currency/converter-EEK-XAG>; rel='alternate'; hreflang='el-GR'\n"
- "Link: <http://www.forexticket-al.com/el/currency/converter-EEK-XAG>; rel='alternate'; hreflang='el-AL'\n"
- "Link: <http://www.forexticket-cy.com/el/currency/converter-EEK-XAG>; rel='alternate'; hreflang='el-CY'\n"
- "Link: <http://www.forexticket.cz/cs/currency/converter-EEK-XAG>; rel='alternate'; hreflang='cs-CZ'\n"
- "Link: <http://www.forexticket.hu/hu/currency/converter-EEK-XAG>; rel='alternate'; hreflang='hu-HU'\n"
- "Link: <http://www.forexticket.se/sv/currency/converter-EEK-XAG>; rel='alternate'; hreflang='sv-SE'\n"
- "Link: <http://www.forexticket.eu/sv/currency/converter-EEK-XAG>; rel='alternate'; hreflang='sv-FI'\n"
- "Link: <http://www.forexticket.co.il/iw/currency/converter-EEK-XAG>; rel='alternate'; hreflang='iw-IL'\n"
- "Link: <http://www.forexticket.co.il/yi/currency/converter-EEK-XAG>; rel='alternate'; hreflang='yi-IL'\n"
- "Link: <http://www.forexticket-bg.com/bg/currency/converter-EEK-XAG>; rel='alternate'; hreflang='bg-BG'\n"
- "Link: <http://www.forexticket.es/ca/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ca-ES'\n"
- "Link: <http://www.forexticket.es/gl/currency/converter-EEK-XAG>; rel='alternate'; hreflang='gl-ES'\n"
- "Link: <http://www.forexticket.dk/da/currency/converter-EEK-XAG>; rel='alternate'; hreflang='da-DK'\n"
- "Link: <http://www.forexticket.eu/fi/currency/converter-EEK-XAG>; rel='alternate'; hreflang='fi-FI'\n"
- "Link: <http://www.forexticket-hr.com/hr/currency/converter-EEK-XAG>; rel='alternate'; hreflang='hr-HR'\n"
- "Link: <http://www.forexticket-hr.com/sr/currency/converter-EEK-XAG>; rel='alternate'; hreflang='sr-HR'\n"
- "Link: <http://www.forexticket.me/sr/currency/converter-EEK-XAG>; rel='alternate'; hreflang='sr-ME'\n"
- "Link: <http://www.forexticket.lt/lt/currency/converter-EEK-XAG>; rel='alternate'; hreflang='lt-LT'\n"
- "Link: <http://www.forexticket-al.com/sq/currency/converter-EEK-XAG>; rel='alternate'; hreflang='sq-AL'\n"
- "Link: <http://www.forexticket.lv/lv/currency/converter-EEK-XAG>; rel='alternate'; hreflang='lv-LV'\n"
- "Link: <http://www.forexticket.co.ee/et/currency/converter-EEK-XAG>; rel='alternate'; hreflang='et-EE'\n"
- "Vary: Accept-Encoding,User-Agent\n"
- "Content-Encoding: gzip\n"
- "Keep-Alive: timeout=1, max=100\n"
- "Connection: Keep-Alive\n"
- "Transfer-Encoding: chunked\n"
- "Content-Type: text/html\n"
- "\n";
+ "Date: Thu, 15 Nov 2012 22:38:28 GMT\n"
+ "Server: Apache/2\n"
+ "X-Powered-By: PHP/5.2.17\n"
+ "Set-Cookie: PHPSESSID=6d69474d1cc019d7d82714c9472bc6d6; path=/\n"
+ "Expires: Thu, 19 Nov 1981 08:52:00 GMT\n"
+ "Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0\n"
+ "Pragma: no-cache\n"
+ "Link: <http://www.forexticket.cn.com/zh/currency/converter-EEK-XAG>; rel='alternate'; hreflang='zh-CN'\n"
+ "Link: <http://www.forexticket.tw/zh/currency/converter-EEK-XAG>; rel='alternate'; hreflang='zh-TW'\n"
+ "Link: <http://www.forexticket.hk/zh/currency/converter-EEK-XAG>; rel='alternate'; hreflang='zh-HK'\n"
+ "Link: <http://www.forexticket.sg/zh/currency/converter-EEK-XAG>; rel='alternate'; hreflang='zh-SG'\n"
+ "Link: <http://www.forexticket.in/hi/currency/converter-EEK-XAG>; rel='alternate'; hreflang='hi-IN'\n"
+ "Link: <http://www.forexticket.com.fj/hi/currency/converter-EEK-XAG>; rel='alternate'; hreflang='hi-FJ'\n"
+ "Link: <http://www.forexticket.in/en/currency/converter-EEK-XAG>; rel='alternate'; hreflang='en-IN'\n"
+ "Link: <http://www.forexticket.us/en/currency/converter-EEK-XAG>; rel='alternate'; hreflang='en-US'\n"
+ "Link: <http://www.forexticket.com.pk/en/currency/converter-EEK-XAG>; rel='alternate'; hreflang='en-PK'\n"
+ "Link: <http://www.forexticket-bd.com/en/currency/converter-EEK-XAG>; rel='alternate'; hreflang='en-BD'\n"
+ "Link: <http://www.forexticket-ng.com/en/currency/converter-EEK-XAG>; rel='alternate'; hreflang='en-NG'\n"
+ "Link: <http://www.forexticket.co.uk/en/currency/converter-EEK-XAG>; rel='alternate'; hreflang='en-GB'\n"
+ "Link: <http://www.forexticket.co.za/en/currency/converter-EEK-XAG>; rel='alternate'; hreflang='en-ZA'\n"
+ "Link: <http://www.forexticket.co.ke/en/currency/converter-EEK-XAG>; rel='alternate'; hreflang='en-KE'\n"
+ "Link: <http://www.forexticket.com/en/currency/converter-EEK-XAG>; rel='alternate'; hreflang='en-CA'\n"
+ "Link: <http://www.forexticket-gh.com/en/currency/converter-EEK-XAG>; rel='alternate'; hreflang='en-GH'\n"
+ "Link: <http://www.forexticket.biz/en/currency/converter-EEK-XAG>; rel='alternate'; hreflang='en-AU'\n"
+ "Link: <http://www.forexticket.cm/en/currency/converter-EEK-XAG>; rel='alternate'; hreflang='en-CM'\n"
+ "Link: <http://www.forexticket-kh.com/en/currency/converter-EEK-XAG>; rel='alternate'; hreflang='en-KH'\n"
+ "Link: <http://www.forexticket.hk/en/currency/converter-EEK-XAG>; rel='alternate'; hreflang='en-HK'\n"
+ "Link: <http://www.forexticket.la/en/currency/converter-EEK-XAG>; rel='alternate'; hreflang='en-LA'\n"
+ "Link: <http://www.forexticket.sg/en/currency/converter-EEK-XAG>; rel='alternate'; hreflang='en-SG'\n"
+ "Link: <http://www.forexticket.co.nz/en/currency/converter-EEK-XAG>; rel='alternate'; hreflang='en-NZ'\n"
+ "Link: <http://www.forexticket.com.pr/en/currency/converter-EEK-XAG>; rel='alternate'; hreflang='en-PR'\n"
+ "Link: <http://www.forexticket.com.fj/en/currency/converter-EEK-XAG>; rel='alternate'; hreflang='en-FJ'\n"
+ "Link: <http://www.forexticket.us/es/cambio/divisas-EEK-XAG>; rel='alternate'; hreflang='es-US'\n"
+ "Link: <http://www.forexticket.mx/es/cambio/divisas-EEK-XAG>; rel='alternate'; hreflang='es-MX'\n"
+ "Link: <http://www.forexticket.co/es/cambio/divisas-EEK-XAG>; rel='alternate'; hreflang='es-CO'\n"
+ "Link: <http://www.forexticket.com.ar/es/cambio/divisas-EEK-XAG>; rel='alternate'; hreflang='es-AR'\n"
+ "Link: <http://www.forexticket-pe.com/es/cambio/divisas-EEK-XAG>; rel='alternate'; hreflang='es-PE'\n"
+ "Link: <http://www.forexticket.co.ve/es/cambio/divisas-EEK-XAG>; rel='alternate'; hreflang='es-VE'\n"
+ "Link: <http://www.forexticket.cl/es/cambio/divisas-EEK-XAG>; rel='alternate'; hreflang='es-CL'\n"
+ "Link: <http://www.forexticket.ec/es/cambio/divisas-EEK-XAG>; rel='alternate'; hreflang='es-EC'\n"
+ "Link: <http://www.forexticket.com.gt/es/cambio/divisas-EEK-XAG>; rel='alternate'; hreflang='es-GT'\n"
+ "Link: <http://www.forexticket.bo/es/cambio/divisas-EEK-XAG>; rel='alternate'; hreflang='es-BO'\n"
+ "Link: <http://www.forexticket.hn/es/cambio/divisas-EEK-XAG>; rel='alternate'; hreflang='es-HN'\n"
+ "Link: <http://www.forexticket.com.py/es/cambio/divisas-EEK-XAG>; rel='alternate'; hreflang='es-PY'\n"
+ "Link: <http://www.forexticket.es/es/cambio/divisas-EEK-XAG>; rel='alternate'; hreflang='es-ES'\n"
+ "Link: <http://www.forexticket.com.sv/es/cambio/divisas-EEK-XAG>; rel='alternate'; hreflang='es-SV'\n"
+ "Link: <http://www.forexticket.com.ni/es/cambio/divisas-EEK-XAG>; rel='alternate'; hreflang='es-NI'\n"
+ "Link: <http://www.forexticket.co.cr/es/cambio/divisas-EEK-XAG>; rel='alternate'; hreflang='es-CR'\n"
+ "Link: <http://www.forexticket.com.pr/es/cambio/divisas-EEK-XAG>; rel='alternate'; hreflang='es-PR'\n"
+ "Link: <http://www.forexticket.com.uy/es/cambio/divisas-EEK-XAG>; rel='alternate'; hreflang='es-UY'\n"
+ "Link: <http://www.forexticket.com.pa/es/cambio/divisas-EEK-XAG>; rel='alternate'; hreflang='es-PA'\n"
+ "Link: <http://www.forexticket.asia.com/id/currency/converter-EEK-XAG>; rel='alternate'; hreflang='id-ID'\n"
+ "Link: <http://www.forexticket.com.br/pt/moeda/conversor-EEK-XAG>; rel='alternate'; hreflang='pt-BR'\n"
+ "Link: <http://www.forexticket-mz.com/pt/moeda/conversor-EEK-XAG>; rel='alternate'; hreflang='pt-MZ'\n"
+ "Link: <http://www.forexticket.com.pt/pt/moeda/conversor-EEK-XAG>; rel='alternate'; hreflang='pt-PT'\n"
+ "Link: <http://www.forexticket.tl/pt/moeda/conversor-EEK-XAG>; rel='alternate'; hreflang='pt-TL'\n"
+ "Link: <http://www.forexticket.ru/ru/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ru-RU'\n"
+ "Link: <http://www.forexticket-kz.com/ru/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ru-KZ'\n"
+ "Link: <http://www.forexticket-tj.com/ru/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ru-TJ'\n"
+ "Link: <http://www.forexticket-kg.com/ru/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ru-KG'\n"
+ "Link: <http://www.forexticket-ge.com/ru/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ru-GE'\n"
+ "Link: <http://www.forexticket.mn/ru/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ru-MN'\n"
+ "Link: <http://www.forexticket.jp/ja/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ja-JP'\n"
+ "Link: <http://www.forexticket-ph.com/tl/currency/converter-EEK-XAG>; rel='alternate'; hreflang='tl-PH'\n"
+ "Link: <http://www.forexticket.vn/vi/currency/converter-EEK-XAG>; rel='alternate'; hreflang='vi-VN'\n"
+ "Link: <http://www.forexticket.de/de/waehrungsumrechner/devisen-EEK-XAG>; rel='alternate'; hreflang='de-DE'\n"
+ "Link: <http://www.forexticket.be/de/waehrungsumrechner/devisen-EEK-XAG>; rel='alternate'; hreflang='de-BE'\n"
+ "Link: <http://www.forexticket.at/de/waehrungsumrechner/devisen-EEK-XAG>; rel='alternate'; hreflang='de-AT'\n"
+ "Link: <http://www.forexticket.ch/de/waehrungsumrechner/devisen-EEK-XAG>; rel='alternate'; hreflang='de-CH'\n"
+ "Link: <http://www.forexticket.lu/de/waehrungsumrechner/devisen-EEK-XAG>; rel='alternate'; hreflang='de-LU'\n"
+ "Link: <http://www.forexticket.li/de/waehrungsumrechner/devisen-EEK-XAG>; rel='alternate'; hreflang='de-LI'\n"
+ "Link: <http://www.forexticket.de/de/waehrungsumrechner/devisen-EEK-XAG>; rel='canonical'\n"
+ "Link: <http://www.forexticket-eg.com/ar/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ar-EG'\n"
+ "Link: <http://www.forexticket-dz.com/ar/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ar-DZ'\n"
+ "Link: <http://www.forexticket-ma.com/ar/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ar-MA'\n"
+ "Link: <http://www.forexticket-iq.com/ar/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ar-IQ'\n"
+ "Link: <http://www.forexticket-sa.com/ar/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ar-SA'\n"
+ "Link: <http://www.forexticket-sy.com/ar/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ar-SY'\n"
+ "Link: <http://www.forexticket-tn.com/ar/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ar-TN'\n"
+ "Link: <http://www.forexticket-td.com/ar/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ar-TD'\n"
+ "Link: <http://www.forexticket-so.com/ar/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ar-SO'\n"
+ "Link: <http://www.forexticket.co.il/ar/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ar-IL'\n"
+ "Link: <http://www.forexticket-jo.com/ar/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ar-JO'\n"
+ "Link: <http://www.forexticket.ae/ar/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ar-AE'\n"
+ "Link: <http://www.forexticket-lb.com/ar/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ar-LB'\n"
+ "Link: <http://www.forexticket-om.com/ar/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ar-OM'\n"
+ "Link: <http://www.forexticket-kw.com/ar/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ar-KW'\n"
+ "Link: <http://www.forexticket-tr.com/tr/currency/converter-EEK-XAG>; rel='alternate'; hreflang='tr-TR'\n"
+ "Link: <http://www.forexticket-bg.com/tr/currency/converter-EEK-XAG>; rel='alternate'; hreflang='tr-BG'\n"
+ "Link: <http://www.forexticket-cy.com/tr/currency/converter-EEK-XAG>; rel='alternate'; hreflang='tr-CY'\n"
+ "Link: <http://www.forexticket.ir/fa/currency/converter-EEK-XAG>; rel='alternate'; hreflang='fa-IR'\n"
+ "Link: <http://www.forexticket.af/fa/currency/converter-EEK-XAG>; rel='alternate'; hreflang='fa-AF'\n"
+ "Link: <http://www.forexticket.cd/fr/conversion/monnaie-EEK-XAG>; rel='alternate'; hreflang='fr-CD'\n"
+ "Link: <http://www.forexticket.fr/fr/conversion/monnaie-EEK-XAG>; rel='alternate'; hreflang='fr-FR'\n"
+ "Link: <http://www.forexticket.com/fr/conversion/monnaie-EEK-XAG>; rel='alternate'; hreflang='fr-CA'\n"
+ "Link: <http://www.forexticket.mg/fr/conversion/monnaie-EEK-XAG>; rel='alternate'; hreflang='fr-MG'\n"
+ "Link: <http://www.forexticket.cm/fr/conversion/monnaie-EEK-XAG>; rel='alternate'; hreflang='fr-CM'\n"
+ "Link: <http://www.forexticket-kh.com/fr/conversion/monnaie-EEK-XAG>; rel='alternate'; hreflang='fr-KH'\n"
+ "Link: <http://www.forexticket-ml.com/fr/conversion/monnaie-EEK-XAG>; rel='alternate'; hreflang='fr-ML'\n"
+ "Link: <http://www.forexticket-sn.com/fr/conversion/monnaie-EEK-XAG>; rel='alternate'; hreflang='fr-SN'\n"
+ "Link: <http://www.forexticket-tn.com/fr/conversion/monnaie-EEK-XAG>; rel='alternate'; hreflang='fr-TN'\n"
+ "Link: <http://www.forexticket-td.com/fr/conversion/monnaie-EEK-XAG>; rel='alternate'; hreflang='fr-TD'\n"
+ "Link: <http://www.forexticket.be/fr/conversion/monnaie-EEK-XAG>; rel='alternate'; hreflang='fr-BE'\n"
+ "Link: <http://www.forexticket-gn.com/fr/conversion/monnaie-EEK-XAG>; rel='alternate'; hreflang='fr-GN'\n"
+ "Link: <http://www.forexticket.ht/fr/conversion/monnaie-EEK-XAG>; rel='alternate'; hreflang='fr-HT'\n"
+ "Link: <http://www.forexticket.ch/fr/conversion/monnaie-EEK-XAG>; rel='alternate'; hreflang='fr-CH'\n"
+ "Link: <http://www.forexticket.la/fr/conversion/monnaie-EEK-XAG>; rel='alternate'; hreflang='fr-LA'\n"
+ "Link: <http://www.forexticket.lu/fr/conversion/monnaie-EEK-XAG>; rel='alternate'; hreflang='fr-LU'\n"
+ "Link: <http://www.forexticket-th.com/th/currency/converter-EEK-XAG>; rel='alternate'; hreflang='th-TH'\n"
+ "Link: <http://www.forexticket.co.uk/cy/currency/converter-EEK-XAG>; rel='alternate'; hreflang='cy-GB'\n"
+ "Link: <http://www.forexticket.co.uk/ga/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ga-GB'\n"
+ "Link: <http://www.forexticket.it/it/convertitore/valuta-EEK-XAG>; rel='alternate'; hreflang='it-IT'\n"
+ "Link: <http://www.forexticket.ch/it/convertitore/valuta-EEK-XAG>; rel='alternate'; hreflang='it-CH'\n"
+ "Link: <http://www.forexticket.co.za/af/currency/converter-EEK-XAG>; rel='alternate'; hreflang='af-ZA'\n"
+ "Link: <http://www.forexticket.kr/ko/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ko-KR'\n"
+ "Link: <http://www.forexticket-ua.com/uk/currency/converter-EEK-XAG>; rel='alternate'; hreflang='uk-UA'\n"
+ "Link: <http://www.forexticket-tz.com/sw/currency/converter-EEK-XAG>; rel='alternate'; hreflang='sw-TZ'\n"
+ "Link: <http://www.forexticket.co.ke/sw/currency/converter-EEK-XAG>; rel='alternate'; hreflang='sw-KE'\n"
+ "Link: <http://www.forexticket.pl/pl/currency/converter-EEK-XAG>; rel='alternate'; hreflang='pl-PL'\n"
+ "Link: <http://www.forexticket.com.my/ms/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ms-MY'\n"
+ "Link: <http://www.forexticket.sg/ms/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ms-SG'\n"
+ "Link: <http://www.forexticket.ro/ro/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ro-RO'\n"
+ "Link: <http://www.forexticket.nl/nl/currency/converter-EEK-XAG>; rel='alternate'; hreflang='nl-NL'\n"
+ "Link: <http://www.forexticket.be/nl/currency/converter-EEK-XAG>; rel='alternate'; hreflang='nl-BE'\n"
+ "Link: <http://www.forexticket.gr/el/currency/converter-EEK-XAG>; rel='alternate'; hreflang='el-GR'\n"
+ "Link: <http://www.forexticket-al.com/el/currency/converter-EEK-XAG>; rel='alternate'; hreflang='el-AL'\n"
+ "Link: <http://www.forexticket-cy.com/el/currency/converter-EEK-XAG>; rel='alternate'; hreflang='el-CY'\n"
+ "Link: <http://www.forexticket.cz/cs/currency/converter-EEK-XAG>; rel='alternate'; hreflang='cs-CZ'\n"
+ "Link: <http://www.forexticket.hu/hu/currency/converter-EEK-XAG>; rel='alternate'; hreflang='hu-HU'\n"
+ "Link: <http://www.forexticket.se/sv/currency/converter-EEK-XAG>; rel='alternate'; hreflang='sv-SE'\n"
+ "Link: <http://www.forexticket.eu/sv/currency/converter-EEK-XAG>; rel='alternate'; hreflang='sv-FI'\n"
+ "Link: <http://www.forexticket.co.il/iw/currency/converter-EEK-XAG>; rel='alternate'; hreflang='iw-IL'\n"
+ "Link: <http://www.forexticket.co.il/yi/currency/converter-EEK-XAG>; rel='alternate'; hreflang='yi-IL'\n"
+ "Link: <http://www.forexticket-bg.com/bg/currency/converter-EEK-XAG>; rel='alternate'; hreflang='bg-BG'\n"
+ "Link: <http://www.forexticket.es/ca/currency/converter-EEK-XAG>; rel='alternate'; hreflang='ca-ES'\n"
+ "Link: <http://www.forexticket.es/gl/currency/converter-EEK-XAG>; rel='alternate'; hreflang='gl-ES'\n"
+ "Link: <http://www.forexticket.dk/da/currency/converter-EEK-XAG>; rel='alternate'; hreflang='da-DK'\n"
+ "Link: <http://www.forexticket.eu/fi/currency/converter-EEK-XAG>; rel='alternate'; hreflang='fi-FI'\n"
+ "Link: <http://www.forexticket-hr.com/hr/currency/converter-EEK-XAG>; rel='alternate'; hreflang='hr-HR'\n"
+ "Link: <http://www.forexticket-hr.com/sr/currency/converter-EEK-XAG>; rel='alternate'; hreflang='sr-HR'\n"
+ "Link: <http://www.forexticket.me/sr/currency/converter-EEK-XAG>; rel='alternate'; hreflang='sr-ME'\n"
+ "Link: <http://www.forexticket.lt/lt/currency/converter-EEK-XAG>; rel='alternate'; hreflang='lt-LT'\n"
+ "Link: <http://www.forexticket-al.com/sq/currency/converter-EEK-XAG>; rel='alternate'; hreflang='sq-AL'\n"
+ "Link: <http://www.forexticket.lv/lv/currency/converter-EEK-XAG>; rel='alternate'; hreflang='lv-LV'\n"
+ "Link: <http://www.forexticket.co.ee/et/currency/converter-EEK-XAG>; rel='alternate'; hreflang='et-EE'\n"
+ "Vary: Accept-Encoding,User-Agent\n"
+ "Content-Encoding: gzip\n"
+ "Keep-Alive: timeout=1, max=100\n"
+ "Connection: Keep-Alive\n"
+ "Transfer-Encoding: chunked\n"
+ "Content-Type: text/html\n"
+ "\n";
diff --git a/library/cpp/http/fetch/ya.make b/library/cpp/http/fetch/ya.make
index 9962b82ee1..7737127463 100644
--- a/library/cpp/http/fetch/ya.make
+++ b/library/cpp/http/fetch/ya.make
@@ -1,19 +1,19 @@
-LIBRARY()
+LIBRARY()
OWNER(
g:zora
)
-PEERDIR(
- contrib/libs/zlib
+PEERDIR(
+ contrib/libs/zlib
library/cpp/charset
library/cpp/digest/md5
library/cpp/http/misc
library/cpp/logger
library/cpp/mime/types
library/cpp/uri
-)
-
+)
+
SRCS(
http_digest.cpp
http_socket.cpp
@@ -32,7 +32,7 @@ SRCS(
GENERATE_ENUM_SERIALIZATION(httpheader.h)
SET(RAGEL6_FLAGS -CF1)
-
+
END()
RECURSE_FOR_TESTS(ut)
diff --git a/library/cpp/http/io/chunk.cpp b/library/cpp/http/io/chunk.cpp
index 80a423e7c9..6975d9eac1 100644
--- a/library/cpp/http/io/chunk.cpp
+++ b/library/cpp/http/io/chunk.cpp
@@ -1,70 +1,70 @@
-#include "chunk.h"
-
+#include "chunk.h"
+
#include "headers.h"
-#include <util/string/cast.h>
-#include <util/generic/utility.h>
-#include <util/generic/yexception.h>
-
+#include <util/string/cast.h>
+#include <util/generic/utility.h>
+#include <util/generic/yexception.h>
+
static inline size_t ParseHex(const TString& s) {
- if (s.empty()) {
+ if (s.empty()) {
ythrow yexception() << "can not parse chunk length(empty string)";
- }
-
- size_t ret = 0;
-
+ }
+
+ size_t ret = 0;
+
for (TString::const_iterator c = s.begin(); c != s.end(); ++c) {
- const char ch = *c;
-
- if (ch >= '0' && ch <= '9') {
- ret *= 16;
- ret += ch - '0';
- } else if (ch >= 'a' && ch <= 'f') {
- ret *= 16;
- ret += 10 + ch - 'a';
- } else if (ch >= 'A' && ch <= 'F') {
- ret *= 16;
- ret += 10 + ch - 'A';
- } else if (ch == ';') {
- break;
- } else if (isspace(ch)) {
- continue;
- } else {
+ const char ch = *c;
+
+ if (ch >= '0' && ch <= '9') {
+ ret *= 16;
+ ret += ch - '0';
+ } else if (ch >= 'a' && ch <= 'f') {
+ ret *= 16;
+ ret += 10 + ch - 'a';
+ } else if (ch >= 'A' && ch <= 'F') {
+ ret *= 16;
+ ret += 10 + ch - 'A';
+ } else if (ch == ';') {
+ break;
+ } else if (isspace(ch)) {
+ continue;
+ } else {
ythrow yexception() << "can not parse chunk length(" << s.data() << ")";
- }
- }
-
- return ret;
-}
-
-static inline char* ToHex(size_t len, char* buf) {
- do {
- const size_t val = len % 16;
-
- *--buf = (val < 10) ? (val + '0') : (val - 10 + 'a');
- len /= 16;
- } while (len);
-
- return buf;
-}
-
-class TChunkedInput::TImpl {
-public:
+ }
+ }
+
+ return ret;
+}
+
+static inline char* ToHex(size_t len, char* buf) {
+ do {
+ const size_t val = len % 16;
+
+ *--buf = (val < 10) ? (val + '0') : (val - 10 + 'a');
+ len /= 16;
+ } while (len);
+
+ return buf;
+}
+
+class TChunkedInput::TImpl {
+public:
inline TImpl(IInputStream* slave, TMaybe<THttpHeaders>* trailers)
- : Slave_(slave)
+ : Slave_(slave)
, Trailers_(trailers)
- , Pending_(0)
- , LastChunkReaded_(false)
- {
+ , Pending_(0)
+ , LastChunkReaded_(false)
+ {
if (Trailers_) {
Trailers_->Clear();
}
- }
-
+ }
+
inline ~TImpl() {
- }
-
- inline size_t Read(void* buf, size_t len) {
+ }
+
+ inline size_t Read(void* buf, size_t len) {
return Perform(len, [this, buf](size_t toRead) { return Slave_->Read(buf, toRead); });
}
@@ -73,174 +73,174 @@ public:
}
private:
- template <class Operation>
+ template <class Operation>
inline size_t Perform(size_t len, const Operation& operation) {
- if (!HavePendingData()) {
- return 0;
- }
-
+ if (!HavePendingData()) {
+ return 0;
+ }
+
const size_t toProcess = Min(Pending_, len);
-
+
if (toProcess) {
const size_t processed = operation(toProcess);
-
+
if (!processed) {
- ythrow yexception() << "malformed http chunk";
- }
-
+ ythrow yexception() << "malformed http chunk";
+ }
+
Pending_ -= processed;
-
+
return processed;
- }
-
- return 0;
- }
-
- inline bool HavePendingData() {
- if (LastChunkReaded_) {
- return false;
- }
-
- if (!Pending_) {
- if (!ProceedToNextChunk()) {
- return false;
- }
- }
-
- return true;
- }
-
- inline bool ProceedToNextChunk() {
+ }
+
+ return 0;
+ }
+
+ inline bool HavePendingData() {
+ if (LastChunkReaded_) {
+ return false;
+ }
+
+ if (!Pending_) {
+ if (!ProceedToNextChunk()) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ inline bool ProceedToNextChunk() {
TString len(Slave_->ReadLine());
-
- if (len.empty()) {
- /*
- * skip crlf from previous chunk
- */
-
- len = Slave_->ReadLine();
- }
-
- Pending_ = ParseHex(len);
-
- if (Pending_) {
- return true;
- }
-
+
+ if (len.empty()) {
+ /*
+ * skip crlf from previous chunk
+ */
+
+ len = Slave_->ReadLine();
+ }
+
+ Pending_ = ParseHex(len);
+
+ if (Pending_) {
+ return true;
+ }
+
if (Trailers_) {
Trailers_->ConstructInPlace(Slave_);
}
- LastChunkReaded_ = true;
-
- return false;
- }
-
-private:
+ LastChunkReaded_ = true;
+
+ return false;
+ }
+
+private:
IInputStream* Slave_;
TMaybe<THttpHeaders>* Trailers_;
- size_t Pending_;
- bool LastChunkReaded_;
-};
-
+ size_t Pending_;
+ bool LastChunkReaded_;
+};
+
TChunkedInput::TChunkedInput(IInputStream* slave, TMaybe<THttpHeaders>* trailers)
: Impl_(new TImpl(slave, trailers))
-{
-}
-
+{
+}
+
TChunkedInput::~TChunkedInput() {
-}
-
-size_t TChunkedInput::DoRead(void* buf, size_t len) {
- return Impl_->Read(buf, len);
-}
-
+}
+
+size_t TChunkedInput::DoRead(void* buf, size_t len) {
+ return Impl_->Read(buf, len);
+}
+
size_t TChunkedInput::DoSkip(size_t len) {
return Impl_->Skip(len);
}
-class TChunkedOutput::TImpl {
+class TChunkedOutput::TImpl {
typedef IOutputStream::TPart TPart;
-
-public:
+
+public:
inline TImpl(IOutputStream* slave)
- : Slave_(slave)
- {
- }
-
+ : Slave_(slave)
+ {
+ }
+
inline ~TImpl() {
- }
-
- inline void Write(const void* buf, size_t len) {
- const char* ptr = (const char*)buf;
-
- while (len) {
- const size_t portion = Min<size_t>(len, 1024 * 16);
-
- WriteImpl(ptr, portion);
-
- ptr += portion;
- len -= portion;
- }
- }
-
- inline void WriteImpl(const void* buf, size_t len) {
- char tmp[32];
- char* e = tmp + sizeof(tmp);
- char* b = ToHex(len, e);
-
- const TPart parts[] = {
- TPart(b, e - b),
- TPart::CrLf(),
- TPart(buf, len),
- TPart::CrLf(),
- };
-
- Slave_->Write(parts, sizeof(parts) / sizeof(*parts));
- }
-
- inline void Flush() {
- Slave_->Flush();
- }
-
- inline void Finish() {
- Slave_->Write("0\r\n\r\n", 5);
-
- Flush();
- }
-
-private:
+ }
+
+ inline void Write(const void* buf, size_t len) {
+ const char* ptr = (const char*)buf;
+
+ while (len) {
+ const size_t portion = Min<size_t>(len, 1024 * 16);
+
+ WriteImpl(ptr, portion);
+
+ ptr += portion;
+ len -= portion;
+ }
+ }
+
+ inline void WriteImpl(const void* buf, size_t len) {
+ char tmp[32];
+ char* e = tmp + sizeof(tmp);
+ char* b = ToHex(len, e);
+
+ const TPart parts[] = {
+ TPart(b, e - b),
+ TPart::CrLf(),
+ TPart(buf, len),
+ TPart::CrLf(),
+ };
+
+ Slave_->Write(parts, sizeof(parts) / sizeof(*parts));
+ }
+
+ inline void Flush() {
+ Slave_->Flush();
+ }
+
+ inline void Finish() {
+ Slave_->Write("0\r\n\r\n", 5);
+
+ Flush();
+ }
+
+private:
IOutputStream* Slave_;
-};
-
+};
+
TChunkedOutput::TChunkedOutput(IOutputStream* slave)
- : Impl_(new TImpl(slave))
-{
-}
-
+ : Impl_(new TImpl(slave))
+{
+}
+
TChunkedOutput::~TChunkedOutput() {
- try {
- Finish();
- } catch (...) {
- }
-}
-
-void TChunkedOutput::DoWrite(const void* buf, size_t len) {
- if (Impl_.Get()) {
- Impl_->Write(buf, len);
- } else {
+ try {
+ Finish();
+ } catch (...) {
+ }
+}
+
+void TChunkedOutput::DoWrite(const void* buf, size_t len) {
+ if (Impl_.Get()) {
+ Impl_->Write(buf, len);
+ } else {
ythrow yexception() << "can not write to finished stream";
- }
-}
-
-void TChunkedOutput::DoFlush() {
- if (Impl_.Get()) {
- Impl_->Flush();
- }
-}
-
-void TChunkedOutput::DoFinish() {
- if (Impl_.Get()) {
- Impl_->Finish();
- Impl_.Destroy();
- }
-}
+ }
+}
+
+void TChunkedOutput::DoFlush() {
+ if (Impl_.Get()) {
+ Impl_->Flush();
+ }
+}
+
+void TChunkedOutput::DoFinish() {
+ if (Impl_.Get()) {
+ Impl_->Finish();
+ Impl_.Destroy();
+ }
+}
diff --git a/library/cpp/http/io/chunk.h b/library/cpp/http/io/chunk.h
index a77f1b1a9d..88d89fafda 100644
--- a/library/cpp/http/io/chunk.h
+++ b/library/cpp/http/io/chunk.h
@@ -1,9 +1,9 @@
#pragma once
-
+
#include <util/stream/output.h>
#include <util/generic/maybe.h>
#include <util/generic/ptr.h>
-
+
class THttpHeaders;
/// @addtogroup Streams_Chunked
@@ -12,36 +12,36 @@ class THttpHeaders;
/// @details Последовательное чтение блоков данных. Предполагается, что
/// данные записаны в виде <длина блока><блок данных>.
class TChunkedInput: public IInputStream {
-public:
+public:
/// Если передан указатель на trailers, то туда будут записаны HTTP trailer'ы (возможно пустые),
/// которые идут после чанков.
TChunkedInput(IInputStream* slave, TMaybe<THttpHeaders>* trailers = nullptr);
~TChunkedInput() override;
-
-private:
+
+private:
size_t DoRead(void* buf, size_t len) override;
size_t DoSkip(size_t len) override;
-
-private:
- class TImpl;
- THolder<TImpl> Impl_;
-};
-
+
+private:
+ class TImpl;
+ THolder<TImpl> Impl_;
+};
+
/// Вывод данных порциями.
/// @details Вывод данных блоками в виде <длина блока><блок данных>. Если объем
/// данных превышает 64K, они записываются в виде n блоков по 64K + то, что осталось.
class TChunkedOutput: public IOutputStream {
-public:
+public:
TChunkedOutput(IOutputStream* slave);
~TChunkedOutput() override;
-
-private:
+
+private:
void DoWrite(const void* buf, size_t len) override;
void DoFlush() override;
void DoFinish() override;
-
-private:
- class TImpl;
- THolder<TImpl> Impl_;
-};
+
+private:
+ class TImpl;
+ THolder<TImpl> Impl_;
+};
/// @}
diff --git a/library/cpp/http/io/chunk_ut.cpp b/library/cpp/http/io/chunk_ut.cpp
index 82f9c90b74..da283f8568 100644
--- a/library/cpp/http/io/chunk_ut.cpp
+++ b/library/cpp/http/io/chunk_ut.cpp
@@ -1,16 +1,16 @@
-#include "chunk.h"
-
+#include "chunk.h"
+
#include <library/cpp/testing/unittest/registar.h>
-
+
#include <util/stream/file.h>
-#include <util/system/tempfile.h>
+#include <util/system/tempfile.h>
#include <util/stream/null.h>
-
-#define CDATA "./chunkedio"
-
+
+#define CDATA "./chunkedio"
+
Y_UNIT_TEST_SUITE(TestChunkedIO) {
- static const char test_data[] = "87s6cfbsudg cuisg s igasidftasiy tfrcua6s";
-
+ static const char test_data[] = "87s6cfbsudg cuisg s igasidftasiy tfrcua6s";
+
TString CombString(const TString& s, size_t chunkSize) {
TString result;
for (size_t pos = 0; pos < s.size(); pos += 2 * chunkSize)
@@ -58,48 +58,48 @@ Y_UNIT_TEST_SUITE(TestChunkedIO) {
}
Y_UNIT_TEST(TestChunkedIo) {
- TTempFile tmpFile(CDATA);
+ TTempFile tmpFile(CDATA);
TString tmp;
-
- {
+
+ {
TUnbufferedFileOutput fo(CDATA);
- TChunkedOutput co(&fo);
+ TChunkedOutput co(&fo);
WriteTestData(&co, &tmp);
}
-
+
{
TUnbufferedFileInput fi(CDATA);
TChunkedInput ci(&fi);
TString r;
-
+
ReadInSmallChunks(&ci, &r);
UNIT_ASSERT_EQUAL(r, tmp);
- }
-
- {
+ }
+
+ {
TUnbufferedFileInput fi(CDATA);
- TChunkedInput ci(&fi);
+ TChunkedInput ci(&fi);
TString r;
-
+
ReadCombed(&ci, &r, 11);
-
+
UNIT_ASSERT_EQUAL(r, CombString(tmp, 11));
- }
- }
-
+ }
+ }
+
Y_UNIT_TEST(TestBadChunk) {
- bool hasError = false;
-
- try {
+ bool hasError = false;
+
+ try {
TString badChunk = "10\r\nqwerty";
TMemoryInput mi(badChunk.data(), badChunk.size());
- TChunkedInput ci(&mi);
- TransferData(&ci, &Cnull);
- } catch (...) {
- hasError = true;
- }
-
- UNIT_ASSERT(hasError);
- }
-}
+ TChunkedInput ci(&mi);
+ TransferData(&ci, &Cnull);
+ } catch (...) {
+ hasError = true;
+ }
+
+ UNIT_ASSERT(hasError);
+ }
+}
diff --git a/library/cpp/http/io/compression.cpp b/library/cpp/http/io/compression.cpp
index 0c922ad566..8fa1f62ae6 100644
--- a/library/cpp/http/io/compression.cpp
+++ b/library/cpp/http/io/compression.cpp
@@ -1,66 +1,66 @@
#include "compression.h"
-
-#if defined(ENABLE_GPL)
+
+#if defined(ENABLE_GPL)
#include <library/cpp/streams/lz/lz.h>
-#endif
-
+#endif
+
#include <library/cpp/streams/brotli/brotli.h>
#include <library/cpp/streams/lzma/lzma.h>
#include <library/cpp/streams/bzip2/bzip2.h>
-
+
#include <library/cpp/blockcodecs/stream.h>
#include <library/cpp/blockcodecs/codecs.h>
-
-#include <util/stream/zlib.h>
-
-
+
+#include <util/stream/zlib.h>
+
+
TCompressionCodecFactory::TCompressionCodecFactory() {
auto gzip = [](auto s) {
return MakeHolder<TZLibDecompress>(s);
- };
-
+ };
+
Add("gzip", gzip, [](auto s) { return MakeHolder<TZLibCompress>(s, ZLib::GZip); });
Add("deflate", gzip, [](auto s) { return MakeHolder<TZLibCompress>(s, ZLib::ZLib); });
Add("br", [](auto s) { return MakeHolder<TBrotliDecompress>(s); }, [](auto s) { return MakeHolder<TBrotliCompress>(s, 4); });
Add("x-gzip", gzip, [](auto s) { return MakeHolder<TZLibCompress>(s, ZLib::GZip); });
Add("x-deflate", gzip, [](auto s) { return MakeHolder<TZLibCompress>(s, ZLib::ZLib); });
-
-#if defined(ENABLE_GPL)
+
+#if defined(ENABLE_GPL)
const ui16 bs = 32 * 1024;
-
+
Add("y-lzo", [](auto s) { return MakeHolder<TLzoDecompress>(s); }, [bs](auto s) { return MakeHolder<TLazy<TLzoCompress> >(s, bs); });
Add("y-lzf", [](auto s) { return MakeHolder<TLzfDecompress>(s); }, [bs](auto s) { return MakeHolder<TLazy<TLzfCompress> >(s, bs); });
Add("y-lzq", [](auto s) { return MakeHolder<TLzqDecompress>(s); }, [bs](auto s) { return MakeHolder<TLazy<TLzqCompress> >(s, bs); });
-#endif
-
+#endif
+
Add("y-bzip2", [](auto s) { return MakeHolder<TBZipDecompress>(s); }, [](auto s) { return MakeHolder<TBZipCompress>(s); });
Add("y-lzma", [](auto s) { return MakeHolder<TLzmaDecompress>(s); }, [](auto s) { return MakeHolder<TLzmaCompress>(s); });
-
+
for (auto codecName : NBlockCodecs::ListAllCodecs()) {
if (codecName.StartsWith("zstd06")) {
continue;
- }
-
+ }
+
if (codecName.StartsWith("zstd08")) {
continue;
- }
-
+ }
+
auto codec = NBlockCodecs::Codec(codecName);
-
+
auto enc = [codec](auto s) {
return MakeHolder<NBlockCodecs::TCodedOutput>(s, codec, 32 * 1024);
};
-
+
auto dec = [codec](auto s) {
return MakeHolder<NBlockCodecs::TDecodedInput>(s, codec);
- };
-
+ };
+
Add(TString("z-") + codecName, dec, enc);
- }
-}
-
+ }
+}
+
void TCompressionCodecFactory::Add(TStringBuf name, TDecoderConstructor d, TEncoderConstructor e) {
Strings_.emplace_back(name);
Codecs_[Strings_.back()] = TCodec{d, e};
BestCodecs_.emplace_back(Strings_.back());
-}
+}
diff --git a/library/cpp/http/io/compression.h b/library/cpp/http/io/compression.h
index b566bbb796..f16c4a18eb 100644
--- a/library/cpp/http/io/compression.h
+++ b/library/cpp/http/io/compression.h
@@ -1,17 +1,17 @@
#pragma once
-
+
#include "stream.h"
-
+
#include <util/generic/deque.h>
#include <util/generic/hash.h>
-
+
class TCompressionCodecFactory {
-public:
+public:
using TDecoderConstructor = std::function<THolder<IInputStream>(IInputStream*)>;
using TEncoderConstructor = std::function<THolder<IOutputStream>(IOutputStream*)>;
-
+
TCompressionCodecFactory();
-
+
static inline TCompressionCodecFactory& Instance() noexcept {
return *SingletonWithPriority<TCompressionCodecFactory, 0>();
}
@@ -20,10 +20,10 @@ public:
if (auto codec = Codecs_.FindPtr(name)) {
return &codec->Decoder;
}
-
+
return nullptr;
}
-
+
inline const TEncoderConstructor* FindEncoder(TStringBuf name) const {
if (auto codec = Codecs_.FindPtr(name)) {
return &codec->Encoder;
@@ -31,23 +31,23 @@ public:
return nullptr;
}
-
+
inline TArrayRef<const TStringBuf> GetBestCodecs() const {
return BestCodecs_;
}
-private:
+private:
void Add(TStringBuf name, TDecoderConstructor d, TEncoderConstructor e);
-
+
struct TCodec {
TDecoderConstructor Decoder;
TEncoderConstructor Encoder;
};
-
+
TDeque<TString> Strings_;
THashMap<TStringBuf, TCodec> Codecs_;
TVector<TStringBuf> BestCodecs_;
-};
+};
namespace NHttp {
template <typename F>
diff --git a/library/cpp/http/io/compression_ut.cpp b/library/cpp/http/io/compression_ut.cpp
index 04a3f85689..2f3d131f8c 100644
--- a/library/cpp/http/io/compression_ut.cpp
+++ b/library/cpp/http/io/compression_ut.cpp
@@ -1,34 +1,34 @@
-#include "stream.h"
+#include "stream.h"
#include "compression.h"
-
+
#include <library/cpp/testing/unittest/registar.h>
#include <library/cpp/testing/unittest/tests_data.h>
-
-#include <util/stream/zlib.h>
+
+#include <util/stream/zlib.h>
#include <util/generic/hash_set.h>
-
+
Y_UNIT_TEST_SUITE(THttpCompressionTest) {
static const TString DATA = "I'm a teapot";
Y_UNIT_TEST(TestGetBestCodecs) {
UNIT_ASSERT(TCompressionCodecFactory::Instance().GetBestCodecs().size() > 0);
- }
+ }
Y_UNIT_TEST(TestEncoder) {
TStringStream buffer;
- {
+ {
auto encoder = TCompressionCodecFactory::Instance().FindEncoder("gzip");
UNIT_ASSERT(encoder);
-
+
auto encodedStream = (*encoder)(&buffer);
encodedStream->Write(DATA);
- }
+ }
TZLibDecompress decompressor(&buffer);
UNIT_ASSERT_EQUAL(decompressor.ReadAll(), DATA);
}
-
+
Y_UNIT_TEST(TestDecoder) {
TStringStream buffer;
diff --git a/library/cpp/http/io/fuzz/main.cpp b/library/cpp/http/io/fuzz/main.cpp
index 60bc30848f..8ded9c7e32 100644
--- a/library/cpp/http/io/fuzz/main.cpp
+++ b/library/cpp/http/io/fuzz/main.cpp
@@ -1,15 +1,15 @@
#include <library/cpp/http/io/stream.h>
-
-#include <util/generic/vector.h>
-#include <util/stream/mem.h>
-
-extern "C" int LLVMFuzzerTestOneInput(const ui8* data, size_t size) {
- TMemoryInput mi(data, size);
-
- try {
- THttpInput(&mi).ReadAll();
- } catch (...) {
- }
-
- return 0; // Non-zero return values are reserved for future use.
-}
+
+#include <util/generic/vector.h>
+#include <util/stream/mem.h>
+
+extern "C" int LLVMFuzzerTestOneInput(const ui8* data, size_t size) {
+ TMemoryInput mi(data, size);
+
+ try {
+ THttpInput(&mi).ReadAll();
+ } catch (...) {
+ }
+
+ return 0; // Non-zero return values are reserved for future use.
+}
diff --git a/library/cpp/http/io/fuzz/ya.make b/library/cpp/http/io/fuzz/ya.make
index 2057830af1..8b3ccb1969 100644
--- a/library/cpp/http/io/fuzz/ya.make
+++ b/library/cpp/http/io/fuzz/ya.make
@@ -1,18 +1,18 @@
FUZZ()
-
+
OWNER(
pg
g:util
)
-
-PEERDIR(
+
+PEERDIR(
library/cpp/http/io
-)
-
+)
+
SIZE(MEDIUM)
-SRCS(
- main.cpp
-)
-
-END()
+SRCS(
+ main.cpp
+)
+
+END()
diff --git a/library/cpp/http/io/headers.cpp b/library/cpp/http/io/headers.cpp
index 5d0d4f895d..4ec27a29e8 100644
--- a/library/cpp/http/io/headers.cpp
+++ b/library/cpp/http/io/headers.cpp
@@ -1,64 +1,64 @@
-#include "headers.h"
-#include "stream.h"
-
+#include "headers.h"
+#include "stream.h"
+
#include <util/generic/strbuf.h>
-#include <util/generic/yexception.h>
+#include <util/generic/yexception.h>
#include <util/stream/output.h>
#include <util/string/ascii.h>
-#include <util/string/cast.h>
-#include <util/string/strip.h>
-
+#include <util/string/cast.h>
+#include <util/string/strip.h>
+
static inline TStringBuf Trim(const char* b, const char* e) noexcept {
- return StripString(TStringBuf(b, e));
-}
-
+ return StripString(TStringBuf(b, e));
+}
+
THttpInputHeader::THttpInputHeader(const TStringBuf header) {
- size_t pos = header.find(':');
-
+ size_t pos = header.find(':');
+
if (pos == TString::npos) {
ythrow THttpParseException() << "can not parse http header(" << TString{header}.Quote() << ")";
- }
-
+ }
+
Name_ = TString(header.cbegin(), header.cbegin() + pos);
Value_ = ::ToString(Trim(header.cbegin() + pos + 1, header.cend()));
-}
-
+}
+
THttpInputHeader::THttpInputHeader(TString name, TString value)
: Name_(std::move(name))
, Value_(std::move(value))
-{
-}
-
+{
+}
+
void THttpInputHeader::OutTo(IOutputStream* stream) const {
typedef IOutputStream::TPart TPart;
-
- const TPart parts[] = {
- TPart(Name_),
- TPart(": ", 2),
- TPart(Value_),
- TPart::CrLf(),
- };
-
- stream->Write(parts, sizeof(parts) / sizeof(*parts));
-}
-
+
+ const TPart parts[] = {
+ TPart(Name_),
+ TPart(": ", 2),
+ TPart(Value_),
+ TPart::CrLf(),
+ };
+
+ stream->Write(parts, sizeof(parts) / sizeof(*parts));
+}
+
THttpHeaders::THttpHeaders(IInputStream* stream) {
TString header;
TString line;
-
+
bool rdOk = stream->ReadLine(header);
while (rdOk && !header.empty()) {
rdOk = stream->ReadLine(line);
-
+
if (rdOk && ((line[0] == ' ') || (line[0] == '\t'))) {
header += line;
} else {
AddHeader(THttpInputHeader(header));
header = line;
- }
- }
-}
-
+ }
+ }
+}
+
bool THttpHeaders::HasHeader(const TStringBuf header) const {
return FindHeader(header);
}
@@ -85,24 +85,24 @@ void THttpHeaders::AddOrReplaceHeader(const THttpInputHeader& header) {
for (auto& hdr : Headers_) {
if (AsciiCompareIgnoreCase(hdr.Name(), header.Name()) == 0) {
hdr = header;
- return;
- }
- }
-
- AddHeader(header);
-}
-
+ return;
+ }
+ }
+
+ AddHeader(header);
+}
+
void THttpHeaders::AddHeader(THttpInputHeader header) {
Headers_.push_back(std::move(header));
-}
-
+}
+
void THttpHeaders::OutTo(IOutputStream* stream) const {
- for (TConstIterator header = Begin(); header != End(); ++header) {
- header->OutTo(stream);
- }
-}
-
-template <>
+ for (TConstIterator header = Begin(); header != End(); ++header) {
+ header->OutTo(stream);
+ }
+}
+
+template <>
void Out<THttpHeaders>(IOutputStream& out, const THttpHeaders& h) {
- h.OutTo(&out);
-}
+ h.OutTo(&out);
+}
diff --git a/library/cpp/http/io/headers.h b/library/cpp/http/io/headers.h
index a6e130eaa0..a71793d1c6 100644
--- a/library/cpp/http/io/headers.h
+++ b/library/cpp/http/io/headers.h
@@ -1,99 +1,99 @@
#pragma once
-
+
#include <util/generic/string.h>
-#include <util/generic/strbuf.h>
+#include <util/generic/strbuf.h>
#include <util/generic/deque.h>
#include <util/generic/vector.h>
#include <util/string/cast.h>
-
+
class IInputStream;
class IOutputStream;
-
+
/// @addtogroup Streams_HTTP
/// @{
/// Объект, содержащий информацию о HTTP-заголовке.
class THttpInputHeader {
-public:
- /// @param[in] header - строка вида 'параметр: значение'.
+public:
+ /// @param[in] header - строка вида 'параметр: значение'.
THttpInputHeader(TStringBuf header);
- /// @param[in] name - имя параметра.
- /// @param[in] value - значение параметра.
+ /// @param[in] name - имя параметра.
+ /// @param[in] value - значение параметра.
THttpInputHeader(TString name, TString value);
-
- /// Возвращает имя параметра.
+
+ /// Возвращает имя параметра.
inline const TString& Name() const noexcept {
- return Name_;
- }
-
- /// Возвращает значение параметра.
+ return Name_;
+ }
+
+ /// Возвращает значение параметра.
inline const TString& Value() const noexcept {
- return Value_;
- }
-
- /// Записывает заголовок вида "имя параметра: значение\r\n" в поток.
+ return Value_;
+ }
+
+ /// Записывает заголовок вида "имя параметра: значение\r\n" в поток.
void OutTo(IOutputStream* stream) const;
-
- /// Возвращает строку "имя параметра: значение".
+
+ /// Возвращает строку "имя параметра: значение".
inline TString ToString() const {
return Name_ + TStringBuf(": ") + Value_;
- }
-
-private:
+ }
+
+private:
TString Name_;
TString Value_;
-};
-
+};
+
/// Контейнер для хранения HTTP-заголовков
-class THttpHeaders {
+class THttpHeaders {
using THeaders = TDeque<THttpInputHeader>;
-
-public:
+
+public:
using TConstIterator = THeaders::const_iterator;
-
+
THttpHeaders() = default;
- /// Добавляет каждую строку из потока в контейнер, считая ее правильным заголовком.
+ /// Добавляет каждую строку из потока в контейнер, считая ее правильным заголовком.
THttpHeaders(IInputStream* stream);
-
- /// Стандартный итератор.
+
+ /// Стандартный итератор.
inline TConstIterator Begin() const noexcept {
- return Headers_.begin();
- }
+ return Headers_.begin();
+ }
inline TConstIterator begin() const noexcept {
return Headers_.begin();
}
-
- /// Стандартный итератор.
+
+ /// Стандартный итератор.
inline TConstIterator End() const noexcept {
- return Headers_.end();
- }
+ return Headers_.end();
+ }
inline TConstIterator end() const noexcept {
return Headers_.end();
}
-
- /// Возвращает количество заголовков в контейнере.
+
+ /// Возвращает количество заголовков в контейнере.
inline size_t Count() const noexcept {
- return Headers_.size();
- }
-
- /// Проверяет, содержит ли контейнер хотя бы один заголовок.
+ return Headers_.size();
+ }
+
+ /// Проверяет, содержит ли контейнер хотя бы один заголовок.
inline bool Empty() const noexcept {
- return Headers_.empty();
- }
+ return Headers_.empty();
+ }
- /// Добавляет заголовок в контейнер.
+ /// Добавляет заголовок в контейнер.
void AddHeader(THttpInputHeader header);
-
+
template <typename ValueType>
void AddHeader(TString name, const ValueType& value) {
AddHeader(THttpInputHeader(std::move(name), ToString(value)));
}
- /// Добавляет заголовок в контейнер, если тот не содержит заголовка
- /// c таким же параметром. В противном случае, заменяет существующий
- /// заголовок на новый.
- void AddOrReplaceHeader(const THttpInputHeader& header);
-
+ /// Добавляет заголовок в контейнер, если тот не содержит заголовка
+ /// c таким же параметром. В противном случае, заменяет существующий
+ /// заголовок на новый.
+ void AddOrReplaceHeader(const THttpInputHeader& header);
+
template <typename ValueType>
void AddOrReplaceHeader(TString name, const ValueType& value) {
AddOrReplaceHeader(THttpInputHeader(std::move(name), ToString(value)));
@@ -109,17 +109,17 @@ public:
/// Возвращает nullptr, если не нашел
const THttpInputHeader* FindHeader(TStringBuf header) const;
- /// Записывает все заголовки контейнера в поток.
- /// @details Каждый заголовк записывается в виде "имя параметра: значение\r\n".
+ /// Записывает все заголовки контейнера в поток.
+ /// @details Каждый заголовк записывается в виде "имя параметра: значение\r\n".
void OutTo(IOutputStream* stream) const;
- /// Обменивает наборы заголовков двух контейнеров.
+ /// Обменивает наборы заголовков двух контейнеров.
void Swap(THttpHeaders& headers) noexcept {
- Headers_.swap(headers.Headers_);
- }
-
-private:
- THeaders Headers_;
-};
-
+ Headers_.swap(headers.Headers_);
+ }
+
+private:
+ THeaders Headers_;
+};
+
/// @}
diff --git a/library/cpp/http/io/headers_ut.cpp b/library/cpp/http/io/headers_ut.cpp
index b68467f786..1d23ef8fdc 100644
--- a/library/cpp/http/io/headers_ut.cpp
+++ b/library/cpp/http/io/headers_ut.cpp
@@ -13,8 +13,8 @@ namespace {
THeadersExistence(const THttpHeaders& headers) {
for (THttpHeaders::TConstIterator it = headers.Begin();
- it != headers.End();
- ++it) {
+ it != headers.End();
+ ++it) {
Add(it->Name(), it->Value());
}
}
@@ -24,7 +24,7 @@ namespace {
Impl.emplace(TString(name), TString(value));
}
- bool operator==(const THeadersExistence& rhs) const {
+ bool operator==(const THeadersExistence& rhs) const {
return Impl == rhs.Impl;
}
@@ -34,11 +34,11 @@ namespace {
};
}
-bool operator==(const THeadersExistence& lhs, const THttpHeaders& rhs) {
+bool operator==(const THeadersExistence& lhs, const THttpHeaders& rhs) {
return lhs == THeadersExistence(rhs);
}
-bool operator==(const THttpHeaders& lhs, const THeadersExistence& rhs) {
+bool operator==(const THttpHeaders& lhs, const THeadersExistence& rhs) {
return THeadersExistence(lhs) == rhs;
}
diff --git a/library/cpp/http/io/list_codings/main.cpp b/library/cpp/http/io/list_codings/main.cpp
index f15b24f234..9818d02bdf 100644
--- a/library/cpp/http/io/list_codings/main.cpp
+++ b/library/cpp/http/io/list_codings/main.cpp
@@ -1,8 +1,8 @@
#include <library/cpp/http/io/stream.h>
-#include <util/stream/output.h>
-
-int main() {
- for (auto codec : SupportedCodings()) {
- Cout << codec << Endl;
- }
-}
+#include <util/stream/output.h>
+
+int main() {
+ for (auto codec : SupportedCodings()) {
+ Cout << codec << Endl;
+ }
+}
diff --git a/library/cpp/http/io/list_codings/ya.make b/library/cpp/http/io/list_codings/ya.make
index 7559ba195c..e5c5fed6dc 100644
--- a/library/cpp/http/io/list_codings/ya.make
+++ b/library/cpp/http/io/list_codings/ya.make
@@ -1,13 +1,13 @@
-PROGRAM()
-
-OWNER(pg)
-
-PEERDIR(
+PROGRAM()
+
+OWNER(pg)
+
+PEERDIR(
library/cpp/http/io
-)
-
-SRCS(
- main.cpp
-)
-
-END()
+)
+
+SRCS(
+ main.cpp
+)
+
+END()
diff --git a/library/cpp/http/io/stream.cpp b/library/cpp/http/io/stream.cpp
index c38faffe0b..6689be684f 100644
--- a/library/cpp/http/io/stream.cpp
+++ b/library/cpp/http/io/stream.cpp
@@ -1,156 +1,156 @@
-#include "stream.h"
+#include "stream.h"
#include "compression.h"
-#include "chunk.h"
-
+#include "chunk.h"
+
#include <util/stream/buffered.h>
-#include <util/stream/length.h>
+#include <util/stream/length.h>
#include <util/stream/multi.h>
#include <util/stream/null.h>
#include <util/stream/tee.h>
-
+
#include <util/system/compat.h>
-#include <util/system/yassert.h>
-
-#include <util/network/socket.h>
-
-#include <util/string/cast.h>
+#include <util/system/yassert.h>
+
+#include <util/network/socket.h>
+
+#include <util/string/cast.h>
#include <util/string/strip.h>
-
+
#include <util/generic/string.h>
-#include <util/generic/utility.h>
-#include <util/generic/hash_set.h>
-#include <util/generic/yexception.h>
-
-#define HEADERCMP(header, str) \
- case sizeof(str) - 1: \
+#include <util/generic/utility.h>
+#include <util/generic/hash_set.h>
+#include <util/generic/yexception.h>
+
+#define HEADERCMP(header, str) \
+ case sizeof(str) - 1: \
if (!stricmp((header).Name().data(), str))
-namespace {
+namespace {
inline size_t SuggestBufferSize() {
- return 8192;
- }
-
+ return 8192;
+ }
+
inline TStringBuf Trim(const char* b, const char* e) noexcept {
- return StripString(TStringBuf(b, e));
- }
-
+ return StripString(TStringBuf(b, e));
+ }
+
inline TStringBuf RmSemiColon(const TStringBuf& s) {
- return s.Before(';');
- }
-
- template <class T, size_t N>
- class TStreams: private TNonCopyable {
- struct TDelete {
- inline void operator()(T* t) noexcept {
- delete t;
- }
- };
-
- typedef T* TPtr;
-
- public:
- inline TStreams() noexcept
- : Beg_(T_ + N)
- {
- }
-
- inline ~TStreams() {
- TDelete f;
-
- ForEach(f);
- }
-
- template <class S>
- inline S* Add(S* t) noexcept {
- return (S*)AddImpl((T*)t);
- }
-
- template <class Functor>
- inline void ForEach(Functor& f) {
- const TPtr* end = T_ + N;
-
- for (TPtr* cur = Beg_; cur != end; ++cur) {
- f(*cur);
- }
- }
-
- TPtr Top() {
- const TPtr* end = T_ + N;
- return end == Beg_ ? nullptr : *Beg_;
- }
-
- private:
- inline T* AddImpl(T* t) noexcept {
- Y_ASSERT(Beg_ > T_);
-
- return (*--Beg_ = t);
- }
-
- private:
- TPtr T_[N];
- TPtr* Beg_;
- };
-
- template <class TStream>
- class TLazy: public IOutputStream {
- public:
- TLazy(IOutputStream* out, ui16 bs)
- : Output_(out)
- , BlockSize_(bs)
- {
- }
-
- void DoWrite(const void* buf, size_t len) override {
- ConstructSlave();
- Slave_->Write(buf, len);
- }
-
- void DoFlush() override {
- ConstructSlave();
- Slave_->Flush();
- }
-
- void DoFinish() override {
- ConstructSlave();
- Slave_->Finish();
- }
-
- private:
- inline void ConstructSlave() {
- if (!Slave_) {
- Slave_.Reset(new TStream(Output_, BlockSize_));
- }
- }
-
- private:
- IOutputStream* Output_;
- ui16 BlockSize_;
- THolder<IOutputStream> Slave_;
- };
-}
-
-class THttpInput::TImpl {
+ return s.Before(';');
+ }
+
+ template <class T, size_t N>
+ class TStreams: private TNonCopyable {
+ struct TDelete {
+ inline void operator()(T* t) noexcept {
+ delete t;
+ }
+ };
+
+ typedef T* TPtr;
+
+ public:
+ inline TStreams() noexcept
+ : Beg_(T_ + N)
+ {
+ }
+
+ inline ~TStreams() {
+ TDelete f;
+
+ ForEach(f);
+ }
+
+ template <class S>
+ inline S* Add(S* t) noexcept {
+ return (S*)AddImpl((T*)t);
+ }
+
+ template <class Functor>
+ inline void ForEach(Functor& f) {
+ const TPtr* end = T_ + N;
+
+ for (TPtr* cur = Beg_; cur != end; ++cur) {
+ f(*cur);
+ }
+ }
+
+ TPtr Top() {
+ const TPtr* end = T_ + N;
+ return end == Beg_ ? nullptr : *Beg_;
+ }
+
+ private:
+ inline T* AddImpl(T* t) noexcept {
+ Y_ASSERT(Beg_ > T_);
+
+ return (*--Beg_ = t);
+ }
+
+ private:
+ TPtr T_[N];
+ TPtr* Beg_;
+ };
+
+ template <class TStream>
+ class TLazy: public IOutputStream {
+ public:
+ TLazy(IOutputStream* out, ui16 bs)
+ : Output_(out)
+ , BlockSize_(bs)
+ {
+ }
+
+ void DoWrite(const void* buf, size_t len) override {
+ ConstructSlave();
+ Slave_->Write(buf, len);
+ }
+
+ void DoFlush() override {
+ ConstructSlave();
+ Slave_->Flush();
+ }
+
+ void DoFinish() override {
+ ConstructSlave();
+ Slave_->Finish();
+ }
+
+ private:
+ inline void ConstructSlave() {
+ if (!Slave_) {
+ Slave_.Reset(new TStream(Output_, BlockSize_));
+ }
+ }
+
+ private:
+ IOutputStream* Output_;
+ ui16 BlockSize_;
+ THolder<IOutputStream> Slave_;
+ };
+}
+
+class THttpInput::TImpl {
typedef THashSet<TString> TAcceptCodings;
-
-public:
+
+public:
inline TImpl(IInputStream* slave)
- : Slave_(slave)
- , Buffered_(Slave_, SuggestBufferSize())
+ : Slave_(slave)
+ , Buffered_(Slave_, SuggestBufferSize())
, ChunkedInput_(nullptr)
, Input_(nullptr)
, FirstLine_(ReadFirstLine(Buffered_))
- , Headers_(&Buffered_)
- , KeepAlive_(false)
- , HasContentLength_(false)
- , ContentLength_(0)
- , ContentEncoded_(false)
+ , Headers_(&Buffered_)
+ , KeepAlive_(false)
+ , HasContentLength_(false)
+ , ContentLength_(0)
+ , ContentEncoded_(false)
, Expect100Continue_(false)
- {
- BuildInputChain();
+ {
+ BuildInputChain();
Y_ASSERT(Input_);
- }
-
+ }
+
static TString ReadFirstLine(TBufferedInput& in) {
TString s;
Y_ENSURE_EX(in.ReadLine(s), THttpReadException() << "Failed to get first line");
@@ -158,48 +158,48 @@ public:
}
inline ~TImpl() {
- }
-
- inline size_t Read(void* buf, size_t len) {
+ }
+
+ inline size_t Read(void* buf, size_t len) {
return Perform(len, [this, buf](size_t toRead) { return Input_->Read(buf, toRead); });
- }
+ }
inline size_t Skip(size_t len) {
return Perform(len, [this](size_t toSkip) { return Input_->Skip(toSkip); });
- }
-
+ }
+
inline const TString& FirstLine() const noexcept {
- return FirstLine_;
- }
-
+ return FirstLine_;
+ }
+
inline const THttpHeaders& Headers() const noexcept {
- return Headers_;
- }
-
+ return Headers_;
+ }
+
inline const TMaybe<THttpHeaders>& Trailers() const noexcept {
return Trailers_;
}
inline bool IsKeepAlive() const noexcept {
- return KeepAlive_;
- }
-
+ return KeepAlive_;
+ }
+
inline bool AcceptEncoding(const TString& s) const {
- return Codings_.find(to_lower(s)) != Codings_.end();
- }
-
+ return Codings_.find(to_lower(s)) != Codings_.end();
+ }
+
inline bool GetContentLength(ui64& value) const noexcept {
- if (HasContentLength_) {
- value = ContentLength_;
- return true;
+ if (HasContentLength_) {
+ value = ContentLength_;
+ return true;
}
- return false;
- }
+ return false;
+ }
inline bool ContentEncoded() const noexcept {
- return ContentEncoded_;
- }
-
+ return ContentEncoded_;
+ }
+
inline bool HasContent() const noexcept {
return HasContentLength_ || ChunkedInput_;
}
@@ -208,8 +208,8 @@ public:
return Expect100Continue_;
}
-private:
- template <class Operation>
+private:
+ template <class Operation>
inline size_t Perform(size_t len, const Operation& operation) {
size_t processed = operation(len);
if (processed == 0 && len > 0) {
@@ -227,52 +227,52 @@ private:
return processed;
}
- struct TParsedHeaders {
+ struct TParsedHeaders {
bool Chunked = false;
bool KeepAlive = false;
- TStringBuf LZipped;
- };
-
- struct TTrEnc {
- inline void operator()(const TStringBuf& s) {
+ TStringBuf LZipped;
+ };
+
+ struct TTrEnc {
+ inline void operator()(const TStringBuf& s) {
if (s == TStringBuf("chunked")) {
p->Chunked = true;
- }
- }
-
- TParsedHeaders* p;
- };
-
- struct TAccCoding {
- inline void operator()(const TStringBuf& s) {
- c->insert(ToString(s));
- }
-
- TAcceptCodings* c;
- };
-
- template <class Functor>
+ }
+ }
+
+ TParsedHeaders* p;
+ };
+
+ struct TAccCoding {
+ inline void operator()(const TStringBuf& s) {
+ c->insert(ToString(s));
+ }
+
+ TAcceptCodings* c;
+ };
+
+ template <class Functor>
inline void ForEach(TString in, Functor& f) {
- in.to_lower();
-
- const char* b = in.begin();
- const char* c = b;
- const char* e = in.end();
-
- while (c != e) {
- if (*c == ',') {
- f(RmSemiColon(Trim(b, c)));
- b = c + 1;
- }
-
- ++c;
- }
-
- if (b != c) {
- f(RmSemiColon(Trim(b, c)));
- }
- }
-
+ in.to_lower();
+
+ const char* b = in.begin();
+ const char* c = b;
+ const char* e = in.end();
+
+ while (c != e) {
+ if (*c == ',') {
+ f(RmSemiColon(Trim(b, c)));
+ b = c + 1;
+ }
+
+ ++c;
+ }
+
+ if (b != c) {
+ f(RmSemiColon(Trim(b, c)));
+ }
+ }
+
inline bool IsRequest() const {
return strnicmp(FirstLine().data(), "get", 3) == 0 ||
strnicmp(FirstLine().data(), "post", 4) == 0 ||
@@ -282,47 +282,47 @@ private:
strnicmp(FirstLine().data(), "delete", 6) == 0;
}
- inline void BuildInputChain() {
- TParsedHeaders p;
+ inline void BuildInputChain() {
+ TParsedHeaders p;
- size_t pos = FirstLine_.rfind(' ');
+ size_t pos = FirstLine_.rfind(' ');
// In HTTP/1.1 Keep-Alive is turned on by default
if (pos != TString::npos && strcmp(FirstLine_.c_str() + pos + 1, "HTTP/1.1") == 0) {
- p.KeepAlive = true; //request
+ p.KeepAlive = true; //request
} else if (strnicmp(FirstLine_.data(), "HTTP/1.1", 8) == 0) {
- p.KeepAlive = true; //reply
- }
-
- for (THttpHeaders::TConstIterator h = Headers_.Begin(); h != Headers_.End(); ++h) {
- const THttpInputHeader& header = *h;
+ p.KeepAlive = true; //reply
+ }
+
+ for (THttpHeaders::TConstIterator h = Headers_.Begin(); h != Headers_.End(); ++h) {
+ const THttpInputHeader& header = *h;
switch (header.Name().size()) {
- HEADERCMP(header, "transfer-encoding") {
- TTrEnc f = {&p};
- ForEach(header.Value(), f);
- }
- break;
- HEADERCMP(header, "content-encoding") {
- p.LZipped = header.Value();
- }
- break;
- HEADERCMP(header, "accept-encoding") {
- TAccCoding f = {&Codings_};
- ForEach(header.Value(), f);
- }
- break;
- HEADERCMP(header, "content-length") {
- HasContentLength_ = true;
- ContentLength_ = FromString(header.Value());
- }
- break;
- HEADERCMP(header, "connection") {
- // accept header "Connection: Keep-Alive, TE"
+ HEADERCMP(header, "transfer-encoding") {
+ TTrEnc f = {&p};
+ ForEach(header.Value(), f);
+ }
+ break;
+ HEADERCMP(header, "content-encoding") {
+ p.LZipped = header.Value();
+ }
+ break;
+ HEADERCMP(header, "accept-encoding") {
+ TAccCoding f = {&Codings_};
+ ForEach(header.Value(), f);
+ }
+ break;
+ HEADERCMP(header, "content-length") {
+ HasContentLength_ = true;
+ ContentLength_ = FromString(header.Value());
+ }
+ break;
+ HEADERCMP(header, "connection") {
+ // accept header "Connection: Keep-Alive, TE"
if (strnicmp(header.Value().data(), "keep-alive", 10) == 0) {
p.KeepAlive = true;
} else if (stricmp(header.Value().data(), "close") == 0) {
p.KeepAlive = false;
}
- }
+ }
[[fallthrough]];
HEADERCMP(header, "expect") {
auto findContinue = [&](const TStringBuf& s) {
@@ -332,101 +332,101 @@ private:
};
ForEach(header.Value(), findContinue);
}
- break;
- }
- }
-
+ break;
+ }
+ }
+
if (p.Chunked) {
ChunkedInput_ = Streams_.Add(new TChunkedInput(&Buffered_, &Trailers_));
Input_ = ChunkedInput_;
- } else {
+ } else {
// disable buffering
- Buffered_.Reset(&Cnull);
- Input_ = Streams_.Add(new TMultiInput(&Buffered_, Slave_));
-
+ Buffered_.Reset(&Cnull);
+ Input_ = Streams_.Add(new TMultiInput(&Buffered_, Slave_));
+
if (IsRequest() || HasContentLength_) {
- /*
- * TODO - we have other cases
- */
- Input_ = Streams_.Add(new TLengthLimitedInput(Input_, ContentLength_));
- }
- }
-
+ /*
+ * TODO - we have other cases
+ */
+ Input_ = Streams_.Add(new TLengthLimitedInput(Input_, ContentLength_));
+ }
+ }
+
if (auto decoder = TCompressionCodecFactory::Instance().FindDecoder(p.LZipped)) {
- ContentEncoded_ = true;
+ ContentEncoded_ = true;
Input_ = Streams_.Add((*decoder)(Input_).Release());
- }
-
+ }
+
KeepAlive_ = p.KeepAlive;
- }
-
-private:
+ }
+
+private:
IInputStream* Slave_;
-
- /*
- * input helpers
- */
- TBufferedInput Buffered_;
+
+ /*
+ * input helpers
+ */
+ TBufferedInput Buffered_;
TStreams<IInputStream, 8> Streams_;
IInputStream* ChunkedInput_;
-
- /*
- * final input stream
- */
+
+ /*
+ * final input stream
+ */
IInputStream* Input_;
-
+
TString FirstLine_;
- THttpHeaders Headers_;
+ THttpHeaders Headers_;
TMaybe<THttpHeaders> Trailers_;
- bool KeepAlive_;
-
- TAcceptCodings Codings_;
+ bool KeepAlive_;
- bool HasContentLength_;
- ui64 ContentLength_;
+ TAcceptCodings Codings_;
- bool ContentEncoded_;
+ bool HasContentLength_;
+ ui64 ContentLength_;
+
+ bool ContentEncoded_;
bool Expect100Continue_;
-};
-
+};
+
THttpInput::THttpInput(IInputStream* slave)
- : Impl_(new TImpl(slave))
-{
-}
-
+ : Impl_(new TImpl(slave))
+{
+}
+
THttpInput::THttpInput(THttpInput&& httpInput) = default;
THttpInput::~THttpInput() {
-}
-
-size_t THttpInput::DoRead(void* buf, size_t len) {
- return Impl_->Read(buf, len);
-}
-
+}
+
+size_t THttpInput::DoRead(void* buf, size_t len) {
+ return Impl_->Read(buf, len);
+}
+
size_t THttpInput::DoSkip(size_t len) {
return Impl_->Skip(len);
}
const THttpHeaders& THttpInput::Headers() const noexcept {
- return Impl_->Headers();
-}
-
+ return Impl_->Headers();
+}
+
const TMaybe<THttpHeaders>& THttpInput::Trailers() const noexcept {
return Impl_->Trailers();
}
const TString& THttpInput::FirstLine() const noexcept {
- return Impl_->FirstLine();
-}
-
+ return Impl_->FirstLine();
+}
+
bool THttpInput::IsKeepAlive() const noexcept {
- return Impl_->IsKeepAlive();
-}
-
+ return Impl_->IsKeepAlive();
+}
+
bool THttpInput::AcceptEncoding(const TString& coding) const {
- return Impl_->AcceptEncoding(coding);
-}
-
+ return Impl_->AcceptEncoding(coding);
+}
+
TString THttpInput::BestCompressionScheme(TArrayRef<const TStringBuf> codings) const {
return NHttp::ChooseBestCompressionScheme(
[this](const TString& coding) {
@@ -434,8 +434,8 @@ TString THttpInput::BestCompressionScheme(TArrayRef<const TStringBuf> codings) c
},
codings
);
-}
-
+}
+
TString THttpInput::BestCompressionScheme() const {
return BestCompressionScheme(TCompressionCodecFactory::Instance().GetBestCodecs());
}
@@ -456,141 +456,141 @@ bool THttpInput::HasExpect100Continue() const noexcept {
return Impl_->HasExpect100Continue();
}
-class THttpOutput::TImpl {
+class THttpOutput::TImpl {
class TSizeCalculator: public IOutputStream {
- public:
+ public:
inline TSizeCalculator() noexcept {
- }
-
+ }
+
~TSizeCalculator() override {
- }
-
+ }
+
void DoWrite(const void* /*buf*/, size_t len) override {
- Length_ += len;
- }
-
+ Length_ += len;
+ }
+
inline size_t Length() const noexcept {
- return Length_;
- }
-
- private:
+ return Length_;
+ }
+
+ private:
size_t Length_ = 0;
- };
-
- enum TState {
- Begin = 0,
- FirstLineSent = 1,
- HeadersSent = 2
- };
-
- struct TFlush {
+ };
+
+ enum TState {
+ Begin = 0,
+ FirstLineSent = 1,
+ HeadersSent = 2
+ };
+
+ struct TFlush {
inline void operator()(IOutputStream* s) {
- s->Flush();
- }
- };
-
- struct TFinish {
+ s->Flush();
+ }
+ };
+
+ struct TFinish {
inline void operator()(IOutputStream* s) {
- s->Finish();
- }
- };
-
-public:
+ s->Finish();
+ }
+ };
+
+public:
inline TImpl(IOutputStream* slave, THttpInput* request)
- : Slave_(slave)
- , State_(Begin)
- , Output_(Slave_)
- , Request_(request)
- , Version_(1100)
- , KeepAliveEnabled_(false)
+ : Slave_(slave)
+ , State_(Begin)
+ , Output_(Slave_)
+ , Request_(request)
+ , Version_(1100)
+ , KeepAliveEnabled_(false)
, BodyEncodingEnabled_(true)
, CompressionHeaderEnabled_(true)
- , Finished_(false)
- {
- }
-
+ , Finished_(false)
+ {
+ }
+
inline ~TImpl() {
- }
-
+ }
+
inline void SendContinue() {
Output_->Write("HTTP/1.1 100 Continue\r\n\r\n");
Output_->Flush();
}
- inline void Write(const void* buf, size_t len) {
- if (Finished_) {
- ythrow THttpException() << "can not write to finished stream";
- }
-
- if (State_ == HeadersSent) {
- Output_->Write(buf, len);
-
- return;
- }
-
- const char* b = (const char*)buf;
- const char* e = b + len;
- const char* c = b;
-
- while (c != e) {
- if (*c == '\n') {
- Line_.append(b, c);
-
+ inline void Write(const void* buf, size_t len) {
+ if (Finished_) {
+ ythrow THttpException() << "can not write to finished stream";
+ }
+
+ if (State_ == HeadersSent) {
+ Output_->Write(buf, len);
+
+ return;
+ }
+
+ const char* b = (const char*)buf;
+ const char* e = b + len;
+ const char* c = b;
+
+ while (c != e) {
+ if (*c == '\n') {
+ Line_.append(b, c);
+
if (!Line_.empty() && Line_.back() == '\r') {
- Line_.pop_back();
- }
-
- b = c + 1;
-
- Process(Line_);
-
- if (State_ == HeadersSent) {
- Output_->Write(b, e - b);
-
- return;
- }
-
- Line_.clear();
- }
-
- ++c;
- }
-
- if (b != c) {
- Line_.append(b, c);
- }
- }
-
- inline void Flush() {
- TFlush f;
- Streams_.ForEach(f);
+ Line_.pop_back();
+ }
+
+ b = c + 1;
+
+ Process(Line_);
+
+ if (State_ == HeadersSent) {
+ Output_->Write(b, e - b);
+
+ return;
+ }
+
+ Line_.clear();
+ }
+
+ ++c;
+ }
+
+ if (b != c) {
+ Line_.append(b, c);
+ }
+ }
+
+ inline void Flush() {
+ TFlush f;
+ Streams_.ForEach(f);
Slave_->Flush(); // see SEARCH-1030
- }
-
- inline void Finish() {
- if (Finished_) {
- return;
- }
-
- TFinish f;
- Streams_.ForEach(f);
+ }
+
+ inline void Finish() {
+ if (Finished_) {
+ return;
+ }
+
+ TFinish f;
+ Streams_.ForEach(f);
Slave_->Finish(); // see SEARCH-1030
-
- Finished_ = true;
- }
-
+
+ Finished_ = true;
+ }
+
inline const THttpHeaders& SentHeaders() const noexcept {
- return Headers_;
- }
-
+ return Headers_;
+ }
+
inline void EnableCompression(TArrayRef<const TStringBuf> schemas) {
- ComprSchemas_ = schemas;
- }
-
- inline void EnableKeepAlive(bool enable) {
- KeepAliveEnabled_ = enable;
- }
-
+ ComprSchemas_ = schemas;
+ }
+
+ inline void EnableKeepAlive(bool enable) {
+ KeepAliveEnabled_ = enable;
+ }
+
inline void EnableBodyEncoding(bool enable) {
BodyEncodingEnabled_ = enable;
}
@@ -601,12 +601,12 @@ public:
inline bool IsCompressionEnabled() const noexcept {
return !ComprSchemas_.empty();
- }
-
+ }
+
inline bool IsKeepAliveEnabled() const noexcept {
- return KeepAliveEnabled_;
- }
-
+ return KeepAliveEnabled_;
+ }
+
inline bool IsBodyEncodingEnabled() const noexcept {
return BodyEncodingEnabled_;
}
@@ -616,9 +616,9 @@ public:
}
inline bool CanBeKeepAlive() const noexcept {
- return SupportChunkedTransfer() && IsKeepAliveEnabled() && (Request_ ? Request_->IsKeepAlive() : true);
- }
-
+ return SupportChunkedTransfer() && IsKeepAliveEnabled() && (Request_ ? Request_->IsKeepAlive() : true);
+ }
+
inline const TString& FirstLine() const noexcept {
return FirstLine_;
}
@@ -627,18 +627,18 @@ public:
return SizeCalculator_.Length();
}
-private:
+private:
static inline bool IsResponse(const TString& s) noexcept {
return strnicmp(s.data(), "HTTP/", 5) == 0;
- }
-
+ }
+
static inline bool IsRequest(const TString& s) noexcept {
- return !IsResponse(s);
- }
-
+ return !IsResponse(s);
+ }
+
inline bool IsHttpRequest() const noexcept {
- return IsRequest(FirstLine_);
- }
+ return IsRequest(FirstLine_);
+ }
inline bool HasResponseBody() const noexcept {
if (IsHttpResponse()) {
@@ -652,169 +652,169 @@ private:
}
inline bool IsHttpResponse() const noexcept {
- return IsResponse(FirstLine_);
- }
-
+ return IsResponse(FirstLine_);
+ }
+
inline bool HasRequestBody() const noexcept {
return strnicmp(FirstLine_.data(), "POST", 4) == 0 ||
strnicmp(FirstLine_.data(), "PATCH", 5) == 0 ||
strnicmp(FirstLine_.data(), "PUT", 3) == 0;
- }
+ }
static inline size_t ParseHttpVersion(const TString& s) {
- if (s.empty()) {
- ythrow THttpParseException() << "malformed http stream";
+ if (s.empty()) {
+ ythrow THttpParseException() << "malformed http stream";
}
-
- size_t parsed_version = 0;
-
- if (IsResponse(s)) {
+
+ size_t parsed_version = 0;
+
+ if (IsResponse(s)) {
const char* b = s.data() + 5;
-
- while (*b && *b != ' ') {
- if (*b != '.') {
- parsed_version *= 10;
- parsed_version += (*b - '0');
- }
-
- ++b;
- }
- } else {
- /*
- * s not empty here
- */
- const char* e = s.end() - 1;
- const char* b = s.begin();
- size_t mult = 1;
-
- while (e != b && *e != '/') {
- if (*e != '.') {
- parsed_version += (*e - '0') * mult;
- mult *= 10;
- }
-
- --e;
- }
- }
-
- return parsed_version * 100;
- }
-
- inline void ParseHttpVersion() {
- size_t parsed_version = ParseHttpVersion(FirstLine_);
-
- if (Request_) {
- parsed_version = Min(parsed_version, ParseHttpVersion(Request_->FirstLine()));
- }
-
- Version_ = parsed_version;
- }
-
+
+ while (*b && *b != ' ') {
+ if (*b != '.') {
+ parsed_version *= 10;
+ parsed_version += (*b - '0');
+ }
+
+ ++b;
+ }
+ } else {
+ /*
+ * s not empty here
+ */
+ const char* e = s.end() - 1;
+ const char* b = s.begin();
+ size_t mult = 1;
+
+ while (e != b && *e != '/') {
+ if (*e != '.') {
+ parsed_version += (*e - '0') * mult;
+ mult *= 10;
+ }
+
+ --e;
+ }
+ }
+
+ return parsed_version * 100;
+ }
+
+ inline void ParseHttpVersion() {
+ size_t parsed_version = ParseHttpVersion(FirstLine_);
+
+ if (Request_) {
+ parsed_version = Min(parsed_version, ParseHttpVersion(Request_->FirstLine()));
+ }
+
+ Version_ = parsed_version;
+ }
+
inline void Process(const TString& s) {
Y_ASSERT(State_ != HeadersSent);
-
- if (State_ == Begin) {
- FirstLine_ = s;
- ParseHttpVersion();
- State_ = FirstLineSent;
- } else {
- if (s.empty()) {
- BuildOutputStream();
- WriteCached();
- State_ = HeadersSent;
- } else {
+
+ if (State_ == Begin) {
+ FirstLine_ = s;
+ ParseHttpVersion();
+ State_ = FirstLineSent;
+ } else {
+ if (s.empty()) {
+ BuildOutputStream();
+ WriteCached();
+ State_ = HeadersSent;
+ } else {
AddHeader(THttpInputHeader(s));
- }
- }
- }
-
+ }
+ }
+ }
+
inline void WriteCachedImpl(IOutputStream* s) const {
s->Write(FirstLine_.data(), FirstLine_.size());
- s->Write("\r\n", 2);
- Headers_.OutTo(s);
- s->Write("\r\n", 2);
- s->Finish();
- }
-
- inline void WriteCached() {
- size_t buflen = 0;
-
- {
- TSizeCalculator out;
-
- WriteCachedImpl(&out);
- buflen = out.Length();
- }
-
- {
- TBufferedOutput out(Slave_, buflen);
-
- WriteCachedImpl(&out);
- }
-
- if (IsHttpRequest() && !HasRequestBody()) {
- /*
- * if this is http request, then send it now
- */
-
- Slave_->Flush();
- }
- }
-
+ s->Write("\r\n", 2);
+ Headers_.OutTo(s);
+ s->Write("\r\n", 2);
+ s->Finish();
+ }
+
+ inline void WriteCached() {
+ size_t buflen = 0;
+
+ {
+ TSizeCalculator out;
+
+ WriteCachedImpl(&out);
+ buflen = out.Length();
+ }
+
+ {
+ TBufferedOutput out(Slave_, buflen);
+
+ WriteCachedImpl(&out);
+ }
+
+ if (IsHttpRequest() && !HasRequestBody()) {
+ /*
+ * if this is http request, then send it now
+ */
+
+ Slave_->Flush();
+ }
+ }
+
inline bool SupportChunkedTransfer() const noexcept {
- return Version_ >= 1100;
- }
-
- inline void BuildOutputStream() {
- if (CanBeKeepAlive()) {
- AddOrReplaceHeader(THttpInputHeader("Connection", "Keep-Alive"));
- } else {
- AddOrReplaceHeader(THttpInputHeader("Connection", "Close"));
- }
-
- if (IsHttpResponse()) {
+ return Version_ >= 1100;
+ }
+
+ inline void BuildOutputStream() {
+ if (CanBeKeepAlive()) {
+ AddOrReplaceHeader(THttpInputHeader("Connection", "Keep-Alive"));
+ } else {
+ AddOrReplaceHeader(THttpInputHeader("Connection", "Close"));
+ }
+
+ if (IsHttpResponse()) {
if (Request_ && IsCompressionEnabled() && HasResponseBody()) {
TString scheme = Request_->BestCompressionScheme(ComprSchemas_);
- if (scheme != "identity") {
- AddOrReplaceHeader(THttpInputHeader("Content-Encoding", scheme));
+ if (scheme != "identity") {
+ AddOrReplaceHeader(THttpInputHeader("Content-Encoding", scheme));
RemoveHeader("Content-Length");
- }
- }
-
- RebuildStream();
- } else {
- if (IsCompressionEnabled()) {
- AddOrReplaceHeader(THttpInputHeader("Accept-Encoding", BuildAcceptEncoding()));
- }
- if (HasRequestBody()) {
- RebuildStream();
- }
- }
- }
-
+ }
+ }
+
+ RebuildStream();
+ } else {
+ if (IsCompressionEnabled()) {
+ AddOrReplaceHeader(THttpInputHeader("Accept-Encoding", BuildAcceptEncoding()));
+ }
+ if (HasRequestBody()) {
+ RebuildStream();
+ }
+ }
+ }
+
inline TString BuildAcceptEncoding() const {
TString ret;
-
+
for (const auto& coding : ComprSchemas_) {
- if (ret) {
- ret += ", ";
- }
-
+ if (ret) {
+ ret += ", ";
+ }
+
ret += coding;
- }
-
- return ret;
- }
+ }
+
+ return ret;
+ }
- inline void RebuildStream() {
+ inline void RebuildStream() {
bool keepAlive = false;
const TCompressionCodecFactory::TEncoderConstructor* encoder = nullptr;
- bool chunked = false;
+ bool chunked = false;
bool haveContentLength = false;
-
- for (THttpHeaders::TConstIterator h = Headers_.Begin(); h != Headers_.End(); ++h) {
- const THttpInputHeader& header = *h;
+
+ for (THttpHeaders::TConstIterator h = Headers_.Begin(); h != Headers_.End(); ++h) {
+ const THttpInputHeader& header = *h;
const TString hl = to_lower(header.Name());
-
+
if (hl == TStringBuf("connection")) {
keepAlive = to_lower(header.Value()) == TStringBuf("keep-alive");
} else if (IsCompressionHeaderEnabled() && hl == TStringBuf("content-encoding")) {
@@ -823,109 +823,109 @@ private:
chunked = to_lower(header.Value()) == TStringBuf("chunked");
} else if (hl == TStringBuf("content-length")) {
haveContentLength = true;
- }
- }
-
+ }
+ }
+
if (!haveContentLength && !chunked && (IsHttpRequest() || HasResponseBody()) && SupportChunkedTransfer() && (keepAlive || encoder || IsHttpRequest())) {
- AddHeader(THttpInputHeader("Transfer-Encoding", "chunked"));
- chunked = true;
- }
-
+ AddHeader(THttpInputHeader("Transfer-Encoding", "chunked"));
+ chunked = true;
+ }
+
if (IsBodyEncodingEnabled() && chunked) {
- Output_ = Streams_.Add(new TChunkedOutput(Output_));
- }
-
+ Output_ = Streams_.Add(new TChunkedOutput(Output_));
+ }
+
Output_ = Streams_.Add(new TTeeOutput(Output_, &SizeCalculator_));
if (IsBodyEncodingEnabled() && encoder) {
Output_ = Streams_.Add((*encoder)(Output_).Release());
- }
- }
-
- inline void AddHeader(const THttpInputHeader& hdr) {
- Headers_.AddHeader(hdr);
- }
-
- inline void AddOrReplaceHeader(const THttpInputHeader& hdr) {
- Headers_.AddOrReplaceHeader(hdr);
- }
-
+ }
+ }
+
+ inline void AddHeader(const THttpInputHeader& hdr) {
+ Headers_.AddHeader(hdr);
+ }
+
+ inline void AddOrReplaceHeader(const THttpInputHeader& hdr) {
+ Headers_.AddOrReplaceHeader(hdr);
+ }
+
inline void RemoveHeader(const TString& hdr) {
Headers_.RemoveHeader(hdr);
}
-private:
+private:
IOutputStream* Slave_;
- TState State_;
+ TState State_;
IOutputStream* Output_;
TStreams<IOutputStream, 8> Streams_;
TString Line_;
TString FirstLine_;
- THttpHeaders Headers_;
- THttpInput* Request_;
- size_t Version_;
-
+ THttpHeaders Headers_;
+ THttpInput* Request_;
+ size_t Version_;
+
TArrayRef<const TStringBuf> ComprSchemas_;
-
- bool KeepAliveEnabled_;
+
+ bool KeepAliveEnabled_;
bool BodyEncodingEnabled_;
bool CompressionHeaderEnabled_;
- bool Finished_;
+ bool Finished_;
TSizeCalculator SizeCalculator_;
-};
-
+};
+
THttpOutput::THttpOutput(IOutputStream* slave)
: Impl_(new TImpl(slave, nullptr))
-{
-}
-
+{
+}
+
THttpOutput::THttpOutput(IOutputStream* slave, THttpInput* request)
- : Impl_(new TImpl(slave, request))
-{
-}
-
+ : Impl_(new TImpl(slave, request))
+{
+}
+
THttpOutput::~THttpOutput() {
- try {
- Finish();
- } catch (...) {
- }
-}
-
-void THttpOutput::DoWrite(const void* buf, size_t len) {
- Impl_->Write(buf, len);
-}
-
-void THttpOutput::DoFlush() {
- Impl_->Flush();
-}
-
-void THttpOutput::DoFinish() {
- Impl_->Finish();
-}
-
+ try {
+ Finish();
+ } catch (...) {
+ }
+}
+
+void THttpOutput::DoWrite(const void* buf, size_t len) {
+ Impl_->Write(buf, len);
+}
+
+void THttpOutput::DoFlush() {
+ Impl_->Flush();
+}
+
+void THttpOutput::DoFinish() {
+ Impl_->Finish();
+}
+
const THttpHeaders& THttpOutput::SentHeaders() const noexcept {
return Impl_->SentHeaders();
-}
-
-void THttpOutput::EnableCompression(bool enable) {
- if (enable) {
+}
+
+void THttpOutput::EnableCompression(bool enable) {
+ if (enable) {
EnableCompression(TCompressionCodecFactory::Instance().GetBestCodecs());
- } else {
+ } else {
TArrayRef<TStringBuf> codings;
EnableCompression(codings);
- }
-}
-
+ }
+}
+
void THttpOutput::EnableCompression(TArrayRef<const TStringBuf> schemas) {
Impl_->EnableCompression(schemas);
-}
-
-void THttpOutput::EnableKeepAlive(bool enable) {
- Impl_->EnableKeepAlive(enable);
-}
-
+}
+
+void THttpOutput::EnableKeepAlive(bool enable) {
+ Impl_->EnableKeepAlive(enable);
+}
+
void THttpOutput::EnableBodyEncoding(bool enable) {
Impl_->EnableBodyEncoding(enable);
}
@@ -935,25 +935,25 @@ void THttpOutput::EnableCompressionHeader(bool enable) {
}
bool THttpOutput::IsKeepAliveEnabled() const noexcept {
- return Impl_->IsKeepAliveEnabled();
-}
-
+ return Impl_->IsKeepAliveEnabled();
+}
+
bool THttpOutput::IsBodyEncodingEnabled() const noexcept {
return Impl_->IsBodyEncodingEnabled();
}
bool THttpOutput::IsCompressionEnabled() const noexcept {
- return Impl_->IsCompressionEnabled();
-}
-
+ return Impl_->IsCompressionEnabled();
+}
+
bool THttpOutput::IsCompressionHeaderEnabled() const noexcept {
return Impl_->IsCompressionHeaderEnabled();
}
bool THttpOutput::CanBeKeepAlive() const noexcept {
- return Impl_->CanBeKeepAlive();
-}
-
+ return Impl_->CanBeKeepAlive();
+}
+
void THttpOutput::SendContinue() {
Impl_->SendContinue();
}
@@ -966,13 +966,13 @@ size_t THttpOutput::SentSize() const noexcept {
return Impl_->SentSize();
}
-unsigned ParseHttpRetCode(const TStringBuf& ret) {
- const TStringBuf code = StripString(StripString(ret.After(' ')).Before(' '));
-
+unsigned ParseHttpRetCode(const TStringBuf& ret) {
+ const TStringBuf code = StripString(StripString(ret.After(' ')).Before(' '));
+
return FromString<unsigned>(code.data(), code.size());
-}
+}
-void SendMinimalHttpRequest(TSocket& s, const TStringBuf& host, const TStringBuf& request, const TStringBuf& agent, const TStringBuf& from) {
+void SendMinimalHttpRequest(TSocket& s, const TStringBuf& host, const TStringBuf& request, const TStringBuf& agent, const TStringBuf& from) {
TSocketOutput so(s);
THttpOutput output(&so);
@@ -995,11 +995,11 @@ void SendMinimalHttpRequest(TSocket& s, const TStringBuf& host, const TStringBuf
IOutputStream::TPart::CrLf(),
IOutputStream::TPart::CrLf(),
};
-
+
output.Write(parts, sizeof(parts) / sizeof(*parts));
output.Finish();
}
-
+
TArrayRef<const TStringBuf> SupportedCodings() {
return TCompressionCodecFactory::Instance().GetBestCodecs();
-}
+}
diff --git a/library/cpp/http/io/stream.h b/library/cpp/http/io/stream.h
index ab69a8abab..78ca4fc814 100644
--- a/library/cpp/http/io/stream.h
+++ b/library/cpp/http/io/stream.h
@@ -1,40 +1,40 @@
#pragma once
-
-#include "headers.h"
-
+
+#include "headers.h"
+
#include <util/stream/output.h>
#include <util/generic/maybe.h>
#include <util/generic/ptr.h>
#include <util/generic/string.h>
-#include <util/generic/strbuf.h>
+#include <util/generic/strbuf.h>
#include <util/generic/yexception.h>
-#include <util/generic/array_ref.h>
-
-class TSocket;
-
-struct THttpException: public yexception {
-};
-
-struct THttpParseException: public THttpException {
-};
-
+#include <util/generic/array_ref.h>
+
+class TSocket;
+
+struct THttpException: public yexception {
+};
+
+struct THttpParseException: public THttpException {
+};
+
struct THttpReadException: public THttpException {
};
/// Чтение ответа HTTP-сервера.
class THttpInput: public IInputStream {
-public:
+public:
THttpInput(IInputStream* slave);
THttpInput(THttpInput&& httpInput);
~THttpInput() override;
-
- /*
- * parsed http headers
- */
- /// Возвращает контейнер с заголовками ответа HTTP-сервера.
+
+ /*
+ * parsed http headers
+ */
+ /// Возвращает контейнер с заголовками ответа HTTP-сервера.
const THttpHeaders& Headers() const noexcept;
-
- /*
+
+ /*
* parsed http trailers
*/
/// Возвращает контейнер (возможно пустой) с trailer'ами ответа HTTP-сервера.
@@ -44,78 +44,78 @@ public:
const TMaybe<THttpHeaders>& Trailers() const noexcept;
/*
- * first line - response or request
- */
- /// Возвращает первую строку ответа HTTP-сервера.
- /// @details Первая строка HTTP-сервера - строка состояния,
- /// содержащая три поля: версию HTTP, код состояния и описание.
+ * first line - response or request
+ */
+ /// Возвращает первую строку ответа HTTP-сервера.
+ /// @details Первая строка HTTP-сервера - строка состояния,
+ /// содержащая три поля: версию HTTP, код состояния и описание.
const TString& FirstLine() const noexcept;
-
- /*
- * connection can be keep-alive
- */
- /// Проверяет, не завершено ли соединение с сервером.
- /// @details Транзакция считается завершенной, если не передан заголовок
- /// "Connection: Keep Alive".
+
+ /*
+ * connection can be keep-alive
+ */
+ /// Проверяет, не завершено ли соединение с сервером.
+ /// @details Транзакция считается завершенной, если не передан заголовок
+ /// "Connection: Keep Alive".
bool IsKeepAlive() const noexcept;
-
- /*
- * output data can be encoded
- */
- /// Проверяет, поддерживается ли данный тип кодирования содержимого
- /// ответа HTTP-сервера.
+
+ /*
+ * output data can be encoded
+ */
+ /// Проверяет, поддерживается ли данный тип кодирования содержимого
+ /// ответа HTTP-сервера.
bool AcceptEncoding(const TString& coding) const;
- /// Пытается определить наилучший тип кодирования ответа HTTP-сервера.
- /// @details Если ответ сервера говорит о том, что поддерживаются
- /// любые типы кодирования, выбирается gzip. В противном случае
- /// из списка типов кодирования выбирается лучший из поддерживаемых сервером.
+ /// Пытается определить наилучший тип кодирования ответа HTTP-сервера.
+ /// @details Если ответ сервера говорит о том, что поддерживаются
+ /// любые типы кодирования, выбирается gzip. В противном случае
+ /// из списка типов кодирования выбирается лучший из поддерживаемых сервером.
TString BestCompressionScheme() const;
TString BestCompressionScheme(TArrayRef<const TStringBuf> codings) const;
-
- /// Если заголовки содержат Content-Length, возвращает true и
- /// записывает значение из заголовка в value
+
+ /// Если заголовки содержат Content-Length, возвращает true и
+ /// записывает значение из заголовка в value
bool GetContentLength(ui64& value) const noexcept;
- /// Признак запакованности данных, - если выставлен, то Content-Length, при наличии в заголовках,
- /// показывает объём запакованных данных, а из THttpInput мы будем вычитывать уже распакованные.
+ /// Признак запакованности данных, - если выставлен, то Content-Length, при наличии в заголовках,
+ /// показывает объём запакованных данных, а из THttpInput мы будем вычитывать уже распакованные.
bool ContentEncoded() const noexcept;
-
+
/// Returns true if Content-Length or Transfer-Encoding header received
bool HasContent() const noexcept;
bool HasExpect100Continue() const noexcept;
-private:
+private:
size_t DoRead(void* buf, size_t len) override;
size_t DoSkip(size_t len) override;
-
-private:
- class TImpl;
- THolder<TImpl> Impl_;
-};
-
+
+private:
+ class TImpl;
+ THolder<TImpl> Impl_;
+};
+
/// Передача запроса HTTP-серверу.
class THttpOutput: public IOutputStream {
-public:
+public:
THttpOutput(IOutputStream* slave);
THttpOutput(IOutputStream* slave, THttpInput* request);
~THttpOutput() override;
-
- /*
- * sent http headers
- */
- /// Возвращает контейнер с заголовками запроса к HTTP-серверу.
+
+ /*
+ * sent http headers
+ */
+ /// Возвращает контейнер с заголовками запроса к HTTP-серверу.
const THttpHeaders& SentHeaders() const noexcept;
-
- /// Устанавливает режим, при котором сервер выдает ответ в упакованном виде.
- void EnableCompression(bool enable);
+
+ /// Устанавливает режим, при котором сервер выдает ответ в упакованном виде.
+ void EnableCompression(bool enable);
void EnableCompression(TArrayRef<const TStringBuf> schemas);
- /// Устанавливает режим, при котором соединение с сервером не завершается
- /// после окончания транзакции.
- void EnableKeepAlive(bool enable);
-
+ /// Устанавливает режим, при котором соединение с сервером не завершается
+ /// после окончания транзакции.
+ void EnableKeepAlive(bool enable);
+
/// Устанавливает режим, при котором тело HTTP-запроса/ответа преобразуется в соответствии
/// с заголовками Content-Encoding и Transfer-Encoding (включен по умолчанию)
void EnableBodyEncoding(bool enable);
@@ -124,12 +124,12 @@ public:
/// указанным в Content-Encoding (включен по умолчанию)
void EnableCompressionHeader(bool enable);
- /// Проверяет, производится ли выдача ответов в упакованном виде.
+ /// Проверяет, производится ли выдача ответов в упакованном виде.
bool IsCompressionEnabled() const noexcept;
- /// Проверяет, не завершается ли соединение с сервером после окончания транзакции.
+ /// Проверяет, не завершается ли соединение с сервером после окончания транзакции.
bool IsKeepAliveEnabled() const noexcept;
-
+
/// Проверяет, преобразуется ли тело HTTP-запроса/ответа в соответствии
/// с заголовками Content-Encoding и Transfer-Encoding
bool IsBodyEncodingEnabled() const noexcept;
@@ -138,13 +138,13 @@ public:
/// указанным в Content-Encoding
bool IsCompressionHeaderEnabled() const noexcept;
- /*
- * is this connection can be really keep-alive
- */
- /// Проверяет, можно ли установить режим, при котором соединение с сервером
- /// не завершается после окончания транзакции.
+ /*
+ * is this connection can be really keep-alive
+ */
+ /// Проверяет, можно ли установить режим, при котором соединение с сервером
+ /// не завершается после окончания транзакции.
bool CanBeKeepAlive() const noexcept;
-
+
void SendContinue();
/*
@@ -157,22 +157,22 @@ public:
/// учёта chunked transfer encoding)
size_t SentSize() const noexcept;
-private:
+private:
void DoWrite(const void* buf, size_t len) override;
void DoFlush() override;
void DoFinish() override;
-
-private:
- class TImpl;
- THolder<TImpl> Impl_;
-};
-
+
+private:
+ class TImpl;
+ THolder<TImpl> Impl_;
+};
+
/// Возвращает код состояния из ответа сервера.
-unsigned ParseHttpRetCode(const TStringBuf& ret);
-
+unsigned ParseHttpRetCode(const TStringBuf& ret);
+
/// Отправляет HTTP-серверу запрос с минимумом необходимых заголовков.
-void SendMinimalHttpRequest(TSocket& s, const TStringBuf& host, const TStringBuf& request, const TStringBuf& agent = "YandexSomething/1.0", const TStringBuf& from = "webadmin@yandex.ru");
+void SendMinimalHttpRequest(TSocket& s, const TStringBuf& host, const TStringBuf& request, const TStringBuf& agent = "YandexSomething/1.0", const TStringBuf& from = "webadmin@yandex.ru");
TArrayRef<const TStringBuf> SupportedCodings();
-
+
/// @}
diff --git a/library/cpp/http/io/stream_ut.cpp b/library/cpp/http/io/stream_ut.cpp
index b597320405..1ea35df675 100644
--- a/library/cpp/http/io/stream_ut.cpp
+++ b/library/cpp/http/io/stream_ut.cpp
@@ -1,19 +1,19 @@
-#include "stream.h"
+#include "stream.h"
#include "chunk.h"
-
+
#include <library/cpp/http/server/http_ex.h>
-
+
#include <library/cpp/testing/unittest/registar.h>
#include <library/cpp/testing/unittest/tests_data.h>
-
-#include <util/string/printf.h>
-#include <util/network/socket.h>
+
+#include <util/string/printf.h>
+#include <util/network/socket.h>
#include <util/stream/file.h>
#include <util/stream/output.h>
#include <util/stream/tee.h>
-#include <util/stream/zlib.h>
+#include <util/stream/zlib.h>
#include <util/stream/null.h>
-
+
Y_UNIT_TEST_SUITE(THttpStreamTest) {
class TTestHttpServer: public THttpServer::ICallBack {
class TRequest: public THttpClientRequestEx {
@@ -34,12 +34,12 @@ Y_UNIT_TEST_SUITE(THttpStreamTest) {
// "lo" is for "local"
if (RD.ServerName() == "yandex.lo") {
// do redirect
- Output() << "HTTP/1.1 301 Moved permanently\r\n"
- "Location: http://www.yandex.lo\r\n"
- "\r\n";
+ Output() << "HTTP/1.1 301 Moved permanently\r\n"
+ "Location: http://www.yandex.lo\r\n"
+ "\r\n";
} else if (RD.ServerName() == "www.yandex.lo") {
- Output() << "HTTP/1.1 200 Ok\r\n"
- "\r\n";
+ Output() << "HTTP/1.1 200 Ok\r\n"
+ "\r\n";
} else {
Output() << "HTTP/1.1 200 Ok\r\n\r\n";
if (Buf.Size()) {
@@ -80,7 +80,7 @@ Y_UNIT_TEST_SUITE(THttpStreamTest) {
Y_UNIT_TEST(TestCodings1) {
UNIT_ASSERT(SupportedCodings().size() > 0);
- }
+ }
Y_UNIT_TEST(TestHttpInput) {
TString res = "I'm a teapot";
@@ -93,41 +93,41 @@ Y_UNIT_TEST_SUITE(THttpStreamTest) {
UNIT_ASSERT(server.Start());
TNetworkAddress addr("localhost", port);
- TSocket s(addr);
-
- //TDebugOutput dbg;
- TNullOutput dbg;
-
- {
- TSocketOutput so(s);
- TTeeOutput out(&so, &dbg);
- THttpOutput output(&out);
-
- output.EnableKeepAlive(true);
- output.EnableCompression(true);
-
+ TSocket s(addr);
+
+ //TDebugOutput dbg;
+ TNullOutput dbg;
+
+ {
+ TSocketOutput so(s);
+ TTeeOutput out(&so, &dbg);
+ THttpOutput output(&out);
+
+ output.EnableKeepAlive(true);
+ output.EnableCompression(true);
+
TString r;
- r += "GET / HTTP/1.1";
- r += "\r\n";
+ r += "GET / HTTP/1.1";
+ r += "\r\n";
r += "Host: yandex.lo";
- r += "\r\n";
- r += "\r\n";
-
+ r += "\r\n";
+ r += "\r\n";
+
output.Write(r.data(), r.size());
- output.Finish();
- }
-
- {
- TSocketInput si(s);
- THttpInput input(&si);
- unsigned httpCode = ParseHttpRetCode(input.FirstLine());
- UNIT_ASSERT_VALUES_EQUAL(httpCode / 10, 30u);
-
- TransferData(&input, &dbg);
- }
+ output.Finish();
+ }
+
+ {
+ TSocketInput si(s);
+ THttpInput input(&si);
+ unsigned httpCode = ParseHttpRetCode(input.FirstLine());
+ UNIT_ASSERT_VALUES_EQUAL(httpCode / 10, 30u);
+
+ TransferData(&input, &dbg);
+ }
server.Stop();
}
-
+
Y_UNIT_TEST(TestHttpInputDelete) {
TString res = "I'm a teapot";
TPortManager pm;
@@ -175,9 +175,9 @@ Y_UNIT_TEST_SUITE(THttpStreamTest) {
}
Y_UNIT_TEST(TestParseHttpRetCode) {
- UNIT_ASSERT_VALUES_EQUAL(ParseHttpRetCode("HTTP/1.1 301"), 301u);
- }
-
+ UNIT_ASSERT_VALUES_EQUAL(ParseHttpRetCode("HTTP/1.1 301"), 301u);
+ }
+
Y_UNIT_TEST(TestKeepAlive) {
{
TString s = "GET / HTTP/1.0\r\n\r\n";
@@ -248,19 +248,19 @@ Y_UNIT_TEST_SUITE(THttpStreamTest) {
TNetworkAddress addr("localhost", port);
- TSocket s(addr);
- TNullOutput dbg;
-
+ TSocket s(addr);
+ TNullOutput dbg;
+
SendMinimalHttpRequest(s, "www.yandex.lo", "/");
-
+
TSocketInput si(s);
- THttpInput input(&si);
+ THttpInput input(&si);
unsigned httpCode = ParseHttpRetCode(input.FirstLine());
- UNIT_ASSERT_VALUES_EQUAL(httpCode, 200u);
-
- TransferData(&input, &dbg);
+ UNIT_ASSERT_VALUES_EQUAL(httpCode, 200u);
+
+ TransferData(&input, &dbg);
server.Stop();
- }
+ }
Y_UNIT_TEST(TestResponseWithBlanks) {
TString res = "qqqqqq\r\n\r\nsdasdsad\r\n";
@@ -276,7 +276,7 @@ Y_UNIT_TEST_SUITE(THttpStreamTest) {
TSocket s(addr);
- SendMinimalHttpRequest(s, "www.yandex.ru", "/");
+ SendMinimalHttpRequest(s, "www.yandex.ru", "/");
TSocketInput si(s);
THttpInput input(&si);
@@ -289,70 +289,70 @@ Y_UNIT_TEST_SUITE(THttpStreamTest) {
Y_UNIT_TEST(TestOutputFlush) {
TString str;
- TStringOutput strOut(str);
- TBufferedOutput bufOut(&strOut, 8192);
- THttpOutput httpOut(&bufOut);
+ TStringOutput strOut(str);
+ TBufferedOutput bufOut(&strOut, 8192);
+ THttpOutput httpOut(&bufOut);
+
+ httpOut.EnableKeepAlive(true);
+ httpOut.EnableCompression(true);
- httpOut.EnableKeepAlive(true);
- httpOut.EnableCompression(true);
-
- const char* header = "GET / HTTP/1.1\r\nHost: yandex.ru\r\n\r\n";
- httpOut << header;
+ const char* header = "GET / HTTP/1.1\r\nHost: yandex.ru\r\n\r\n";
+ httpOut << header;
unsigned curLen = str.size();
- const char* body = "<html>Hello</html>";
- httpOut << body;
+ const char* body = "<html>Hello</html>";
+ httpOut << body;
UNIT_ASSERT_VALUES_EQUAL(curLen, str.size());
- httpOut.Flush();
+ httpOut.Flush();
UNIT_ASSERT_VALUES_EQUAL(curLen + strlen(body), str.size());
- }
+ }
Y_UNIT_TEST(TestOutputPostFlush) {
TString str;
TString checkStr;
- TStringOutput strOut(str);
- TStringOutput checkOut(checkStr);
- TBufferedOutput bufOut(&strOut, 8192);
- TTeeOutput teeOut(&bufOut, &checkOut);
- THttpOutput httpOut(&teeOut);
+ TStringOutput strOut(str);
+ TStringOutput checkOut(checkStr);
+ TBufferedOutput bufOut(&strOut, 8192);
+ TTeeOutput teeOut(&bufOut, &checkOut);
+ THttpOutput httpOut(&teeOut);
- httpOut.EnableKeepAlive(true);
- httpOut.EnableCompression(true);
+ httpOut.EnableKeepAlive(true);
+ httpOut.EnableCompression(true);
- const char* header = "POST / HTTP/1.1\r\nHost: yandex.ru\r\n\r\n";
- httpOut << header;
+ const char* header = "POST / HTTP/1.1\r\nHost: yandex.ru\r\n\r\n";
+ httpOut << header;
UNIT_ASSERT_VALUES_EQUAL(str.size(), 0u);
- const char* body = "<html>Hello</html>";
- httpOut << body;
+ const char* body = "<html>Hello</html>";
+ httpOut << body;
UNIT_ASSERT_VALUES_EQUAL(str.size(), 0u);
- httpOut.Flush();
+ httpOut.Flush();
UNIT_ASSERT_VALUES_EQUAL(checkStr.size(), str.size());
- }
+ }
TString MakeHttpOutputBody(const char* body, bool encodingEnabled) {
TString str;
- TStringOutput strOut(str);
- {
- TBufferedOutput bufOut(&strOut, 8192);
- THttpOutput httpOut(&bufOut);
+ TStringOutput strOut(str);
+ {
+ TBufferedOutput bufOut(&strOut, 8192);
+ THttpOutput httpOut(&bufOut);
- httpOut.EnableKeepAlive(true);
- httpOut.EnableCompression(true);
+ httpOut.EnableKeepAlive(true);
+ httpOut.EnableCompression(true);
httpOut.EnableBodyEncoding(encodingEnabled);
- httpOut << "POST / HTTP/1.1\r\n";
- httpOut << "Host: yandex.ru\r\n";
- httpOut << "Content-Encoding: gzip\r\n";
- httpOut << "\r\n";
+ httpOut << "POST / HTTP/1.1\r\n";
+ httpOut << "Host: yandex.ru\r\n";
+ httpOut << "Content-Encoding: gzip\r\n";
+ httpOut << "\r\n";
UNIT_ASSERT_VALUES_EQUAL(str.size(), 0u);
- httpOut << body;
- }
- const char* bodyDelimiter = "\r\n\r\n";
- size_t bodyPos = str.find(bodyDelimiter);
+ httpOut << body;
+ }
+ const char* bodyDelimiter = "\r\n\r\n";
+ size_t bodyPos = str.find(bodyDelimiter);
UNIT_ASSERT(bodyPos != TString::npos);
return str.substr(bodyPos + strlen(bodyDelimiter));
};
@@ -370,54 +370,54 @@ Y_UNIT_TEST_SUITE(THttpStreamTest) {
const char* body = "<html>Hello</html>";
UNIT_ASSERT(MakeHttpOutputBody(body, false) == body);
UNIT_ASSERT(MakeHttpOutputBody(body, true) == SimulateBodyEncoding(body));
- }
-
+ }
+
Y_UNIT_TEST(TestOutputFinish) {
TString str;
- TStringOutput strOut(str);
- TBufferedOutput bufOut(&strOut, 8192);
+ TStringOutput strOut(str);
+ TBufferedOutput bufOut(&strOut, 8192);
THttpOutput httpOut(&bufOut);
httpOut.EnableKeepAlive(true);
httpOut.EnableCompression(true);
- const char* header = "GET / HTTP/1.1\r\nHost: yandex.ru\r\n\r\n";
- httpOut << header;
+ const char* header = "GET / HTTP/1.1\r\nHost: yandex.ru\r\n\r\n";
+ httpOut << header;
unsigned curLen = str.size();
- const char* body = "<html>Hello</html>";
+ const char* body = "<html>Hello</html>";
httpOut << body;
UNIT_ASSERT_VALUES_EQUAL(curLen, str.size());
- httpOut.Finish();
+ httpOut.Finish();
UNIT_ASSERT_VALUES_EQUAL(curLen + strlen(body), str.size());
}
Y_UNIT_TEST(TestMultilineHeaders) {
- const char* headerLine0 = "HTTP/1.1 200 OK";
- const char* headerLine1 = "Content-Language: en";
- const char* headerLine2 = "Vary: Accept-Encoding, ";
- const char* headerLine3 = "\tAccept-Language";
- const char* headerLine4 = "Content-Length: 18";
+ const char* headerLine0 = "HTTP/1.1 200 OK";
+ const char* headerLine1 = "Content-Language: en";
+ const char* headerLine2 = "Vary: Accept-Encoding, ";
+ const char* headerLine3 = "\tAccept-Language";
+ const char* headerLine4 = "Content-Length: 18";
TString endLine("\r\n");
TString r;
- r += headerLine0 + endLine;
- r += headerLine1 + endLine;
- r += headerLine2 + endLine;
- r += headerLine3 + endLine;
- r += headerLine4 + endLine + endLine;
- r += "<html>Hello</html>";
- TStringInput stringInput(r);
- THttpInput input(&stringInput);
-
- const THttpHeaders& httpHeaders = input.Headers();
- UNIT_ASSERT_VALUES_EQUAL(httpHeaders.Count(), 3u);
-
- THttpHeaders::TConstIterator it = httpHeaders.Begin();
+ r += headerLine0 + endLine;
+ r += headerLine1 + endLine;
+ r += headerLine2 + endLine;
+ r += headerLine3 + endLine;
+ r += headerLine4 + endLine + endLine;
+ r += "<html>Hello</html>";
+ TStringInput stringInput(r);
+ THttpInput input(&stringInput);
+
+ const THttpHeaders& httpHeaders = input.Headers();
+ UNIT_ASSERT_VALUES_EQUAL(httpHeaders.Count(), 3u);
+
+ THttpHeaders::TConstIterator it = httpHeaders.Begin();
UNIT_ASSERT_VALUES_EQUAL(it->ToString(), TString(headerLine1));
UNIT_ASSERT_VALUES_EQUAL((++it)->ToString(), TString::Join(headerLine2, headerLine3));
UNIT_ASSERT_VALUES_EQUAL((++it)->ToString(), TString(headerLine4));
- }
+ }
Y_UNIT_TEST(ContentLengthRemoval) {
TMemoryInput request("GET / HTTP/1.1\r\nAccept-Encoding: gzip\r\n\r\n");
@@ -430,8 +430,8 @@ Y_UNIT_TEST_SUITE(THttpStreamTest) {
httpOut.EnableCompression(true);
httpOut << "HTTP/1.1 200 OK\r\n";
char answer[] = "Mary had a little lamb.";
- httpOut << "Content-Length: " << strlen(answer) << "\r\n"
- "\r\n";
+ httpOut << "Content-Length: " << strlen(answer) << "\r\n"
+ "\r\n";
httpOut << answer;
httpOut.Finish();
@@ -541,9 +541,9 @@ Y_UNIT_TEST_SUITE(THttpStreamTest) {
TStringStream request;
{
THttpOutput httpOutput(&request);
- httpOutput << "POST / HTTP/1.1\r\n"
- "Host: yandex.ru\r\n"
- "\r\n";
+ httpOutput << "POST / HTTP/1.1\r\n"
+ "Host: yandex.ru\r\n"
+ "\r\n";
httpOutput << "GGLOL";
}
{
@@ -568,9 +568,9 @@ Y_UNIT_TEST_SUITE(THttpStreamTest) {
Y_UNIT_TEST(TestInputHasContent) {
{
TStringStream request;
- request << "POST / HTTP/1.1\r\n"
- "Host: yandex.ru\r\n"
- "\r\n";
+ request << "POST / HTTP/1.1\r\n"
+ "Host: yandex.ru\r\n"
+ "\r\n";
request << "HTTPDATA";
TStringInput input(request.Str());
@@ -582,10 +582,10 @@ Y_UNIT_TEST_SUITE(THttpStreamTest) {
{
TStringStream request;
- request << "POST / HTTP/1.1\r\n"
- "Host: yandex.ru\r\n"
- "Content-Length: 8"
- "\r\n\r\n";
+ request << "POST / HTTP/1.1\r\n"
+ "Host: yandex.ru\r\n"
+ "Content-Length: 8"
+ "\r\n\r\n";
request << "HTTPDATA";
TStringInput input(request.Str());
@@ -597,10 +597,10 @@ Y_UNIT_TEST_SUITE(THttpStreamTest) {
{
TStringStream request;
- request << "POST / HTTP/1.1\r\n"
- "Host: yandex.ru\r\n"
- "Transfer-Encoding: chunked"
- "\r\n\r\n";
+ request << "POST / HTTP/1.1\r\n"
+ "Host: yandex.ru\r\n"
+ "Transfer-Encoding: chunked"
+ "\r\n\r\n";
request << "8\r\nHTTPDATA\r\n0\r\n";
TStringInput input(request.Str());
@@ -612,10 +612,10 @@ Y_UNIT_TEST_SUITE(THttpStreamTest) {
}
Y_UNIT_TEST(TestHttpInputHeadRequest) {
- class THeadOnlyInput: public IInputStream {
+ class THeadOnlyInput: public IInputStream {
public:
THeadOnlyInput() = default;
-
+
private:
size_t DoRead(void* buf, size_t len) override {
if (Eof_) {
@@ -635,8 +635,8 @@ Y_UNIT_TEST_SUITE(THttpStreamTest) {
private:
TString Data_{TStringBuf("HEAD / HTTP/1.1\r\nHost: yandex.ru\r\n\r\n")};
- size_t Pos_{0};
- bool Eof_{false};
+ size_t Pos_{0};
+ bool Eof_{false};
};
THeadOnlyInput input;
THttpInput httpInput(&input);
@@ -647,10 +647,10 @@ Y_UNIT_TEST_SUITE(THttpStreamTest) {
Y_UNIT_TEST(TestHttpOutputResponseToHeadRequestNoZeroChunk) {
TStringStream request;
- request << "HEAD / HTTP/1.1\r\n"
- "Host: yandex.ru\r\n"
- "Connection: Keep-Alive\r\n"
- "\r\n";
+ request << "HEAD / HTTP/1.1\r\n"
+ "Host: yandex.ru\r\n"
+ "Connection: Keep-Alive\r\n"
+ "\r\n";
TStringInput input(request.Str());
THttpInput httpInput(&input);
diff --git a/library/cpp/http/io/stream_ut_medium.cpp b/library/cpp/http/io/stream_ut_medium.cpp
index e70d47555d..2c125eb21e 100644
--- a/library/cpp/http/io/stream_ut_medium.cpp
+++ b/library/cpp/http/io/stream_ut_medium.cpp
@@ -1,54 +1,54 @@
-#include "stream.h"
+#include "stream.h"
#include <library/cpp/testing/unittest/registar.h>
-#include <util/stream/zlib.h>
-
+#include <util/stream/zlib.h>
+
Y_UNIT_TEST_SUITE(THttpTestMedium) {
Y_UNIT_TEST(TestCodings2) {
- TStringBuf data = "aaaaaaaaaaaaaaaaaaaaaaa";
-
- for (auto codec : SupportedCodings()) {
+ TStringBuf data = "aaaaaaaaaaaaaaaaaaaaaaa";
+
+ for (auto codec : SupportedCodings()) {
if (codec == TStringBuf("z-zlib-0")) {
- continue;
- }
-
+ continue;
+ }
+
if (codec == TStringBuf("z-null")) {
- continue;
- }
-
- TString s;
-
- {
- TStringOutput so(s);
- THttpOutput ho(&so);
- TBufferedOutput bo(&ho, 10000);
-
- bo << "HTTP/1.1 200 Ok\r\n"
- << "Connection: close\r\n"
- << "Content-Encoding: " << codec << "\r\n\r\n";
-
- for (size_t i = 0; i < 100; ++i) {
- bo << data;
- }
- }
-
- try {
+ continue;
+ }
+
+ TString s;
+
+ {
+ TStringOutput so(s);
+ THttpOutput ho(&so);
+ TBufferedOutput bo(&ho, 10000);
+
+ bo << "HTTP/1.1 200 Ok\r\n"
+ << "Connection: close\r\n"
+ << "Content-Encoding: " << codec << "\r\n\r\n";
+
+ for (size_t i = 0; i < 100; ++i) {
+ bo << data;
+ }
+ }
+
+ try {
UNIT_ASSERT(s.size() > 10);
- UNIT_ASSERT(s.find(data) == TString::npos);
- } catch (...) {
- Cerr << codec << " " << s << Endl;
-
- throw;
- }
-
- {
- TStringInput si(s);
- THttpInput hi(&si);
-
- auto res = hi.ReadAll();
-
- UNIT_ASSERT(res.find(data) == 0);
- }
- }
- }
-
+ UNIT_ASSERT(s.find(data) == TString::npos);
+ } catch (...) {
+ Cerr << codec << " " << s << Endl;
+
+ throw;
+ }
+
+ {
+ TStringInput si(s);
+ THttpInput hi(&si);
+
+ auto res = hi.ReadAll();
+
+ UNIT_ASSERT(res.find(data) == 0);
+ }
+ }
+ }
+
} // THttpTestMedium suite
diff --git a/library/cpp/http/io/ut/medium/ya.make b/library/cpp/http/io/ut/medium/ya.make
index 24d16b00ea..235a23dcd7 100644
--- a/library/cpp/http/io/ut/medium/ya.make
+++ b/library/cpp/http/io/ut/medium/ya.make
@@ -1,11 +1,11 @@
UNITTEST_FOR(library/cpp/http/io)
-
+
SIZE(MEDIUM)
OWNER(g:util)
-
-SRCS(
+
+SRCS(
stream_ut_medium.cpp
-)
-
-END()
+)
+
+END()
diff --git a/library/cpp/http/io/ut/ya.make b/library/cpp/http/io/ut/ya.make
index ea0597ebb6..84f6949db3 100644
--- a/library/cpp/http/io/ut/ya.make
+++ b/library/cpp/http/io/ut/ya.make
@@ -1,16 +1,16 @@
UNITTEST_FOR(library/cpp/http/io)
-
+
OWNER(g:util)
-
+
PEERDIR(
library/cpp/http/server
)
-SRCS(
- chunk_ut.cpp
+SRCS(
+ chunk_ut.cpp
compression_ut.cpp
headers_ut.cpp
- stream_ut.cpp
-)
-
-END()
+ stream_ut.cpp
+)
+
+END()
diff --git a/library/cpp/http/io/ya.make b/library/cpp/http/io/ya.make
index 83b30c8958..dcfbd79885 100644
--- a/library/cpp/http/io/ya.make
+++ b/library/cpp/http/io/ya.make
@@ -1,22 +1,22 @@
-LIBRARY()
-
+LIBRARY()
+
OWNER(
g:util
mvel
)
-
-PEERDIR(
+
+PEERDIR(
library/cpp/blockcodecs
library/cpp/streams/brotli
library/cpp/streams/bzip2
library/cpp/streams/lzma
-)
-
-SRCS(
- chunk.cpp
+)
+
+SRCS(
+ chunk.cpp
compression.cpp
- headers.cpp
+ headers.cpp
stream.cpp
-)
-
-END()
+)
+
+END()
diff --git a/library/cpp/http/misc/httpcodes.cpp b/library/cpp/http/misc/httpcodes.cpp
index fb9e43c9d3..ad8c80ac1e 100644
--- a/library/cpp/http/misc/httpcodes.cpp
+++ b/library/cpp/http/misc/httpcodes.cpp
@@ -2,26 +2,26 @@
TStringBuf HttpCodeStrEx(int code) noexcept {
switch (code) {
- case HTTP_CONTINUE:
+ case HTTP_CONTINUE:
return TStringBuf("100 Continue");
- case HTTP_SWITCHING_PROTOCOLS:
+ case HTTP_SWITCHING_PROTOCOLS:
return TStringBuf("101 Switching protocols");
case HTTP_PROCESSING:
return TStringBuf("102 Processing");
-
- case HTTP_OK:
+
+ case HTTP_OK:
return TStringBuf("200 Ok");
- case HTTP_CREATED:
+ case HTTP_CREATED:
return TStringBuf("201 Created");
- case HTTP_ACCEPTED:
+ case HTTP_ACCEPTED:
return TStringBuf("202 Accepted");
- case HTTP_NON_AUTHORITATIVE_INFORMATION:
+ case HTTP_NON_AUTHORITATIVE_INFORMATION:
return TStringBuf("203 None authoritative information");
- case HTTP_NO_CONTENT:
+ case HTTP_NO_CONTENT:
return TStringBuf("204 No content");
- case HTTP_RESET_CONTENT:
+ case HTTP_RESET_CONTENT:
return TStringBuf("205 Reset content");
- case HTTP_PARTIAL_CONTENT:
+ case HTTP_PARTIAL_CONTENT:
return TStringBuf("206 Partial content");
case HTTP_MULTI_STATUS:
return TStringBuf("207 Multi status");
@@ -30,58 +30,58 @@ TStringBuf HttpCodeStrEx(int code) noexcept {
case HTTP_IM_USED:
return TStringBuf("226 IM used");
- case HTTP_MULTIPLE_CHOICES:
+ case HTTP_MULTIPLE_CHOICES:
return TStringBuf("300 Multiple choices");
- case HTTP_MOVED_PERMANENTLY:
+ case HTTP_MOVED_PERMANENTLY:
return TStringBuf("301 Moved permanently");
- case HTTP_FOUND:
+ case HTTP_FOUND:
return TStringBuf("302 Moved temporarily");
- case HTTP_SEE_OTHER:
+ case HTTP_SEE_OTHER:
return TStringBuf("303 See other");
- case HTTP_NOT_MODIFIED:
+ case HTTP_NOT_MODIFIED:
return TStringBuf("304 Not modified");
- case HTTP_USE_PROXY:
+ case HTTP_USE_PROXY:
return TStringBuf("305 Use proxy");
- case HTTP_TEMPORARY_REDIRECT:
+ case HTTP_TEMPORARY_REDIRECT:
return TStringBuf("307 Temporarily redirect");
case HTTP_PERMANENT_REDIRECT:
return TStringBuf("308 Permanent redirect");
- case HTTP_BAD_REQUEST:
+ case HTTP_BAD_REQUEST:
return TStringBuf("400 Bad request");
- case HTTP_UNAUTHORIZED:
+ case HTTP_UNAUTHORIZED:
return TStringBuf("401 Unauthorized");
- case HTTP_PAYMENT_REQUIRED:
+ case HTTP_PAYMENT_REQUIRED:
return TStringBuf("402 Payment required");
- case HTTP_FORBIDDEN:
+ case HTTP_FORBIDDEN:
return TStringBuf("403 Forbidden");
- case HTTP_NOT_FOUND:
+ case HTTP_NOT_FOUND:
return TStringBuf("404 Not found");
- case HTTP_METHOD_NOT_ALLOWED:
+ case HTTP_METHOD_NOT_ALLOWED:
return TStringBuf("405 Method not allowed");
- case HTTP_NOT_ACCEPTABLE:
+ case HTTP_NOT_ACCEPTABLE:
return TStringBuf("406 Not acceptable");
- case HTTP_PROXY_AUTHENTICATION_REQUIRED:
+ case HTTP_PROXY_AUTHENTICATION_REQUIRED:
return TStringBuf("407 Proxy Authentication required");
- case HTTP_REQUEST_TIME_OUT:
+ case HTTP_REQUEST_TIME_OUT:
return TStringBuf("408 Request time out");
- case HTTP_CONFLICT:
+ case HTTP_CONFLICT:
return TStringBuf("409 Conflict");
- case HTTP_GONE:
+ case HTTP_GONE:
return TStringBuf("410 Gone");
- case HTTP_LENGTH_REQUIRED:
+ case HTTP_LENGTH_REQUIRED:
return TStringBuf("411 Length required");
- case HTTP_PRECONDITION_FAILED:
+ case HTTP_PRECONDITION_FAILED:
return TStringBuf("412 Precondition failed");
- case HTTP_REQUEST_ENTITY_TOO_LARGE:
+ case HTTP_REQUEST_ENTITY_TOO_LARGE:
return TStringBuf("413 Request entity too large");
- case HTTP_REQUEST_URI_TOO_LARGE:
+ case HTTP_REQUEST_URI_TOO_LARGE:
return TStringBuf("414 Request uri too large");
- case HTTP_UNSUPPORTED_MEDIA_TYPE:
+ case HTTP_UNSUPPORTED_MEDIA_TYPE:
return TStringBuf("415 Unsupported media type");
- case HTTP_REQUESTED_RANGE_NOT_SATISFIABLE:
+ case HTTP_REQUESTED_RANGE_NOT_SATISFIABLE:
return TStringBuf("416 Requested Range Not Satisfiable");
- case HTTP_EXPECTATION_FAILED:
+ case HTTP_EXPECTATION_FAILED:
return TStringBuf("417 Expectation Failed");
case HTTP_I_AM_A_TEAPOT:
return TStringBuf("418 I Am A Teapot");
@@ -89,7 +89,7 @@ TStringBuf HttpCodeStrEx(int code) noexcept {
return TStringBuf("419 Authentication Timeout");
case HTTP_MISDIRECTED_REQUEST:
return TStringBuf("421 Misdirected Request");
- case HTTP_UNPROCESSABLE_ENTITY:
+ case HTTP_UNPROCESSABLE_ENTITY:
return TStringBuf("422 Unprocessable Entity");
case HTTP_LOCKED:
return TStringBuf("423 Locked");
@@ -101,24 +101,24 @@ TStringBuf HttpCodeStrEx(int code) noexcept {
return TStringBuf("426 Upgrade Required");
case HTTP_PRECONDITION_REQUIRED:
return TStringBuf("428 Precondition Required");
- case HTTP_TOO_MANY_REQUESTS:
+ case HTTP_TOO_MANY_REQUESTS:
return TStringBuf("429 Too Many Requests");
case HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE:
return TStringBuf("431 Request Header Fields Too Large");
case HTTP_UNAVAILABLE_FOR_LEGAL_REASONS:
return TStringBuf("451 Unavailable For Legal Reason");
- case HTTP_INTERNAL_SERVER_ERROR:
+ case HTTP_INTERNAL_SERVER_ERROR:
return TStringBuf("500 Internal server error");
- case HTTP_NOT_IMPLEMENTED:
+ case HTTP_NOT_IMPLEMENTED:
return TStringBuf("501 Not implemented");
- case HTTP_BAD_GATEWAY:
+ case HTTP_BAD_GATEWAY:
return TStringBuf("502 Bad gateway");
- case HTTP_SERVICE_UNAVAILABLE:
+ case HTTP_SERVICE_UNAVAILABLE:
return TStringBuf("503 Service unavailable");
- case HTTP_GATEWAY_TIME_OUT:
+ case HTTP_GATEWAY_TIME_OUT:
return TStringBuf("504 Gateway time out");
- case HTTP_HTTP_VERSION_NOT_SUPPORTED:
+ case HTTP_HTTP_VERSION_NOT_SUPPORTED:
return TStringBuf("505 HTTP version not supported");
case HTTP_VARIANT_ALSO_NEGOTIATES:
return TStringBuf("506 Variant also negotiates");
@@ -135,7 +135,7 @@ TStringBuf HttpCodeStrEx(int code) noexcept {
case HTTP_UNASSIGNED_512:
return TStringBuf("512 Unassigned");
- default:
+ default:
return TStringBuf("000 Unknown HTTP code");
}
}
diff --git a/library/cpp/http/misc/httpcodes.h b/library/cpp/http/misc/httpcodes.h
index 2b7a3c4a80..cbfbaa1188 100644
--- a/library/cpp/http/misc/httpcodes.h
+++ b/library/cpp/http/misc/httpcodes.h
@@ -3,67 +3,67 @@
#include <util/generic/strbuf.h>
enum HttpCodes {
- HTTP_CONTINUE = 100,
- HTTP_SWITCHING_PROTOCOLS = 101,
+ HTTP_CONTINUE = 100,
+ HTTP_SWITCHING_PROTOCOLS = 101,
HTTP_PROCESSING = 102,
- HTTP_OK = 200,
- HTTP_CREATED = 201,
- HTTP_ACCEPTED = 202,
- HTTP_NON_AUTHORITATIVE_INFORMATION = 203,
- HTTP_NO_CONTENT = 204,
- HTTP_RESET_CONTENT = 205,
- HTTP_PARTIAL_CONTENT = 206,
+ HTTP_OK = 200,
+ HTTP_CREATED = 201,
+ HTTP_ACCEPTED = 202,
+ HTTP_NON_AUTHORITATIVE_INFORMATION = 203,
+ HTTP_NO_CONTENT = 204,
+ HTTP_RESET_CONTENT = 205,
+ HTTP_PARTIAL_CONTENT = 206,
HTTP_MULTI_STATUS = 207,
HTTP_ALREADY_REPORTED = 208,
HTTP_IM_USED = 226,
- HTTP_MULTIPLE_CHOICES = 300,
- HTTP_MOVED_PERMANENTLY = 301,
- HTTP_FOUND = 302,
- HTTP_SEE_OTHER = 303,
- HTTP_NOT_MODIFIED = 304,
- HTTP_USE_PROXY = 305,
- HTTP_TEMPORARY_REDIRECT = 307,
+ HTTP_MULTIPLE_CHOICES = 300,
+ HTTP_MOVED_PERMANENTLY = 301,
+ HTTP_FOUND = 302,
+ HTTP_SEE_OTHER = 303,
+ HTTP_NOT_MODIFIED = 304,
+ HTTP_USE_PROXY = 305,
+ HTTP_TEMPORARY_REDIRECT = 307,
HTTP_PERMANENT_REDIRECT = 308,
- HTTP_BAD_REQUEST = 400,
- HTTP_UNAUTHORIZED = 401,
- HTTP_PAYMENT_REQUIRED = 402,
- HTTP_FORBIDDEN = 403,
- HTTP_NOT_FOUND = 404,
- HTTP_METHOD_NOT_ALLOWED = 405,
- HTTP_NOT_ACCEPTABLE = 406,
- HTTP_PROXY_AUTHENTICATION_REQUIRED = 407,
- HTTP_REQUEST_TIME_OUT = 408,
- HTTP_CONFLICT = 409,
- HTTP_GONE = 410,
- HTTP_LENGTH_REQUIRED = 411,
- HTTP_PRECONDITION_FAILED = 412,
- HTTP_REQUEST_ENTITY_TOO_LARGE = 413,
- HTTP_REQUEST_URI_TOO_LARGE = 414,
- HTTP_UNSUPPORTED_MEDIA_TYPE = 415,
- HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416,
- HTTP_EXPECTATION_FAILED = 417,
+ HTTP_BAD_REQUEST = 400,
+ HTTP_UNAUTHORIZED = 401,
+ HTTP_PAYMENT_REQUIRED = 402,
+ HTTP_FORBIDDEN = 403,
+ HTTP_NOT_FOUND = 404,
+ HTTP_METHOD_NOT_ALLOWED = 405,
+ HTTP_NOT_ACCEPTABLE = 406,
+ HTTP_PROXY_AUTHENTICATION_REQUIRED = 407,
+ HTTP_REQUEST_TIME_OUT = 408,
+ HTTP_CONFLICT = 409,
+ HTTP_GONE = 410,
+ HTTP_LENGTH_REQUIRED = 411,
+ HTTP_PRECONDITION_FAILED = 412,
+ HTTP_REQUEST_ENTITY_TOO_LARGE = 413,
+ HTTP_REQUEST_URI_TOO_LARGE = 414,
+ HTTP_UNSUPPORTED_MEDIA_TYPE = 415,
+ HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416,
+ HTTP_EXPECTATION_FAILED = 417,
HTTP_I_AM_A_TEAPOT = 418,
HTTP_AUTHENTICATION_TIMEOUT = 419,
HTTP_MISDIRECTED_REQUEST = 421,
- HTTP_UNPROCESSABLE_ENTITY = 422,
+ HTTP_UNPROCESSABLE_ENTITY = 422,
HTTP_LOCKED = 423,
HTTP_FAILED_DEPENDENCY = 424,
HTTP_UNORDERED_COLLECTION = 425,
HTTP_UPGRADE_REQUIRED = 426,
HTTP_PRECONDITION_REQUIRED = 428,
- HTTP_TOO_MANY_REQUESTS = 429,
+ HTTP_TOO_MANY_REQUESTS = 429,
HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE = 431,
HTTP_UNAVAILABLE_FOR_LEGAL_REASONS = 451,
- HTTP_INTERNAL_SERVER_ERROR = 500,
- HTTP_NOT_IMPLEMENTED = 501,
- HTTP_BAD_GATEWAY = 502,
- HTTP_SERVICE_UNAVAILABLE = 503,
- HTTP_GATEWAY_TIME_OUT = 504,
- HTTP_HTTP_VERSION_NOT_SUPPORTED = 505,
+ HTTP_INTERNAL_SERVER_ERROR = 500,
+ HTTP_NOT_IMPLEMENTED = 501,
+ HTTP_BAD_GATEWAY = 502,
+ HTTP_SERVICE_UNAVAILABLE = 503,
+ HTTP_GATEWAY_TIME_OUT = 504,
+ HTTP_HTTP_VERSION_NOT_SUPPORTED = 505,
HTTP_VARIANT_ALSO_NEGOTIATES = 506,
HTTP_INSUFFICIENT_STORAGE = 507,
HTTP_LOOP_DETECTED = 508,
diff --git a/library/cpp/http/misc/httpdate.cpp b/library/cpp/http/misc/httpdate.cpp
index 98876293c6..4a3031bbf4 100644
--- a/library/cpp/http/misc/httpdate.cpp
+++ b/library/cpp/http/misc/httpdate.cpp
@@ -43,7 +43,7 @@
static const char *wkdays[] = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};
-
+
static const char *months[] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct",
"Nov", "Dec"
@@ -64,15 +64,15 @@ int format_http_date(char buf[], size_t size, time_t when) {
#endif
}
-char* format_http_date(time_t when, char* buf, size_t buflen) {
- const int len = format_http_date(buf, buflen, when);
-
- if (len == 0) {
+char* format_http_date(time_t when, char* buf, size_t buflen) {
+ const int len = format_http_date(buf, buflen, when);
+
+ if (len == 0) {
return nullptr;
- }
-
+ }
+
Y_ASSERT(len > 0 && size_t(len) < buflen);
-
+
return buf;
}
diff --git a/library/cpp/http/misc/httpdate.h b/library/cpp/http/misc/httpdate.h
index 0640624661..04876f38fe 100644
--- a/library/cpp/http/misc/httpdate.h
+++ b/library/cpp/http/misc/httpdate.h
@@ -1,11 +1,11 @@
#pragma once
-#include <util/datetime/base.h>
+#include <util/datetime/base.h>
#include <util/generic/string.h>
-
+
#include <ctime>
-#define BAD_DATE ((time_t)-1)
+#define BAD_DATE ((time_t)-1)
inline time_t parse_http_date(const TStringBuf& datestring) {
try {
@@ -16,6 +16,6 @@ inline time_t parse_http_date(const TStringBuf& datestring) {
}
int format_http_date(char buf[], size_t size, time_t when);
-char* format_http_date(time_t when, char* buf, size_t len);
+char* format_http_date(time_t when, char* buf, size_t len);
TString FormatHttpDate(time_t when);
diff --git a/library/cpp/http/misc/httpdate_ut.cpp b/library/cpp/http/misc/httpdate_ut.cpp
index ac4e54063e..c1a0103501 100644
--- a/library/cpp/http/misc/httpdate_ut.cpp
+++ b/library/cpp/http/misc/httpdate_ut.cpp
@@ -1,15 +1,15 @@
#include <library/cpp/testing/unittest/registar.h>
-
-#include "httpdate.h"
-
+
+#include "httpdate.h"
+
Y_UNIT_TEST_SUITE(TestHttpDate) {
Y_UNIT_TEST(Test1) {
- char buf1[100];
- char buf2[100];
-
- UNIT_ASSERT((int)strlen(format_http_date(0, buf1, sizeof(buf1))) == format_http_date(buf2, sizeof(buf2), 0));
- }
+ char buf1[100];
+ char buf2[100];
+
+ UNIT_ASSERT((int)strlen(format_http_date(0, buf1, sizeof(buf1))) == format_http_date(buf2, sizeof(buf2), 0));
+ }
Y_UNIT_TEST(Test2) {
UNIT_ASSERT_STRINGS_EQUAL(FormatHttpDate(1234567890), "Fri, 13 Feb 2009 23:31:30 GMT");
}
-}
+}
diff --git a/library/cpp/http/misc/httpreqdata.cpp b/library/cpp/http/misc/httpreqdata.cpp
index ecc55e754d..f6951f68cd 100644
--- a/library/cpp/http/misc/httpreqdata.cpp
+++ b/library/cpp/http/misc/httpreqdata.cpp
@@ -1,51 +1,51 @@
-#include "httpreqdata.h"
-
+#include "httpreqdata.h"
+
#include <util/stream/mem.h>
TBaseServerRequestData::TBaseServerRequestData(SOCKET s)
: Addr(nullptr)
- , Host()
- , Port()
+ , Host()
+ , Port()
, Path(nullptr)
, Search(nullptr)
- , SearchLength(0)
- , Socket(s)
- , BeginTime(MicroSeconds())
-{
-}
-
+ , SearchLength(0)
+ , Socket(s)
+ , BeginTime(MicroSeconds())
+{
+}
+
TBaseServerRequestData::TBaseServerRequestData(const char* qs, SOCKET s)
: Addr(nullptr)
- , Host()
- , Port()
+ , Host()
+ , Port()
, Path(nullptr)
- , Search((char*)qs)
- , SearchLength(qs ? strlen(qs) : 0)
+ , Search((char*)qs)
+ , SearchLength(qs ? strlen(qs) : 0)
, OrigSearch(Search, SearchLength)
- , Socket(s)
- , BeginTime(MicroSeconds())
-{
-}
-
+ , Socket(s)
+ , BeginTime(MicroSeconds())
+{
+}
+
void TBaseServerRequestData::AppendQueryString(const char* str, size_t length) {
- if (Y_UNLIKELY(Search)) {
+ if (Y_UNLIKELY(Search)) {
Y_ASSERT(strlen(Search) == SearchLength);
ModifiedQueryString.Reserve(SearchLength + length + 2);
ModifiedQueryString.Assign(Search, SearchLength);
- if (SearchLength > 0 && Search[SearchLength - 1] != '&' &&
- length > 0 && str[0] != '&') {
+ if (SearchLength > 0 && Search[SearchLength - 1] != '&' &&
+ length > 0 && str[0] != '&') {
ModifiedQueryString.Append('&');
- }
+ }
ModifiedQueryString.Append(str, length);
- } else {
+ } else {
ModifiedQueryString.Reserve(length + 1);
ModifiedQueryString.Assign(str, length);
- }
+ }
ModifiedQueryString.Append('\0');
Search = ModifiedQueryString.data();
SearchLength = ModifiedQueryString.size() - 1; // ignore terminator
-}
-
+}
+
void TBaseServerRequestData::SetRemoteAddr(TStringBuf addr) {
TMemoryOutput out(AddrData, Y_ARRAY_SIZE(AddrData) - 1);
out.Write(addr.substr(0, Y_ARRAY_SIZE(AddrData) - 1));
@@ -55,142 +55,142 @@ void TBaseServerRequestData::SetRemoteAddr(TStringBuf addr) {
}
const char* TBaseServerRequestData::RemoteAddr() const {
- if (!Addr) {
- *AddrData = 0;
- GetRemoteAddr(Socket, AddrData, sizeof(AddrData));
- Addr = AddrData;
- }
-
- return Addr;
-}
-
+ if (!Addr) {
+ *AddrData = 0;
+ GetRemoteAddr(Socket, AddrData, sizeof(AddrData));
+ Addr = AddrData;
+ }
+
+ return Addr;
+}
+
const char* TBaseServerRequestData::HeaderIn(TStringBuf key) const {
auto it = HeadersIn_.find(key);
-
+
if (it == HeadersIn_.end()) {
return nullptr;
- }
-
+ }
+
return it->second.data();
-}
-
+}
+
TString TBaseServerRequestData::HeaderByIndex(size_t n) const noexcept {
- if (n >= HeadersCount()) {
+ if (n >= HeadersCount()) {
return nullptr;
- }
-
+ }
+
THttpHeadersContainer::const_iterator i = HeadersIn_.begin();
-
- while (n) {
- ++i;
- --n;
- }
-
+
+ while (n) {
+ ++i;
+ --n;
+ }
+
return TString(i->first) + TStringBuf(": ") + i->second;
-}
-
+}
+
const char* TBaseServerRequestData::Environment(const char* key) const {
- if (stricmp(key, "REMOTE_ADDR") == 0) {
- const char* ip = HeaderIn("X-Real-IP");
- if (ip)
- return ip;
- return RemoteAddr();
- } else if (stricmp(key, "QUERY_STRING") == 0) {
- return QueryString();
- } else if (stricmp(key, "SERVER_NAME") == 0) {
+ if (stricmp(key, "REMOTE_ADDR") == 0) {
+ const char* ip = HeaderIn("X-Real-IP");
+ if (ip)
+ return ip;
+ return RemoteAddr();
+ } else if (stricmp(key, "QUERY_STRING") == 0) {
+ return QueryString();
+ } else if (stricmp(key, "SERVER_NAME") == 0) {
return ServerName().data();
- } else if (stricmp(key, "SERVER_PORT") == 0) {
+ } else if (stricmp(key, "SERVER_PORT") == 0) {
return ServerPort().data();
- } else if (stricmp(key, "SCRIPT_NAME") == 0) {
- return ScriptName();
- }
+ } else if (stricmp(key, "SCRIPT_NAME") == 0) {
+ return ScriptName();
+ }
return nullptr;
-}
-
+}
+
void TBaseServerRequestData::Clear() {
HeadersIn_.clear();
Addr = Path = Search = nullptr;
OrigSearch = {};
- SearchLength = 0;
- Host.clear();
- Port.clear();
- CurPage.remove();
+ SearchLength = 0;
+ Host.clear();
+ Port.clear();
+ CurPage.remove();
ParseBuf.Clear();
- BeginTime = MicroSeconds();
-}
-
+ BeginTime = MicroSeconds();
+}
+
const char* TBaseServerRequestData::GetCurPage() const {
- if (!CurPage && Host) {
- CurPage = "http://";
- CurPage += Host;
- if (Port) {
- CurPage += ':';
- CurPage += Port;
- }
- CurPage += Path;
- if (Search) {
- CurPage += '?';
- CurPage += Search;
- }
- }
+ if (!CurPage && Host) {
+ CurPage = "http://";
+ CurPage += Host;
+ if (Port) {
+ CurPage += ':';
+ CurPage += Port;
+ }
+ CurPage += Path;
+ if (Search) {
+ CurPage += '?';
+ CurPage += Search;
+ }
+ }
return CurPage.data();
-}
-
+}
+
bool TBaseServerRequestData::Parse(const char* origReq) {
- size_t origReqLength = strlen(origReq);
+ size_t origReqLength = strlen(origReq);
ParseBuf.Assign(origReq, origReqLength + 1);
char* req = ParseBuf.Data();
-
- while (*req == ' ' || *req == '\t')
- req++;
- if (*req != '/')
- return false; // we are not a proxy
- while (req[1] == '/') // remove redundant slashes
- req++;
-
- // detect url end (can contain some garbage after whitespace, e.g. 'HTTP 1.1')
- char* urlEnd = req;
- while (*urlEnd && *urlEnd != ' ' && *urlEnd != '\t')
- urlEnd++;
- if (*urlEnd)
- *urlEnd = 0;
-
- // cut fragment if exists
- char* fragment = strchr(req, '#');
- if (fragment)
- *fragment = 0; // ignore fragment
- else
- fragment = urlEnd;
- Path = req;
-
- // calculate Search length without additional strlen-ing
- Search = strchr(Path, '?');
- if (Search) {
- *Search++ = 0;
- ptrdiff_t delta = fragment - Search;
- // indeed, second case is a parse error
- SearchLength = (delta >= 0) ? delta : (urlEnd - Search);
+
+ while (*req == ' ' || *req == '\t')
+ req++;
+ if (*req != '/')
+ return false; // we are not a proxy
+ while (req[1] == '/') // remove redundant slashes
+ req++;
+
+ // detect url end (can contain some garbage after whitespace, e.g. 'HTTP 1.1')
+ char* urlEnd = req;
+ while (*urlEnd && *urlEnd != ' ' && *urlEnd != '\t')
+ urlEnd++;
+ if (*urlEnd)
+ *urlEnd = 0;
+
+ // cut fragment if exists
+ char* fragment = strchr(req, '#');
+ if (fragment)
+ *fragment = 0; // ignore fragment
+ else
+ fragment = urlEnd;
+ Path = req;
+
+ // calculate Search length without additional strlen-ing
+ Search = strchr(Path, '?');
+ if (Search) {
+ *Search++ = 0;
+ ptrdiff_t delta = fragment - Search;
+ // indeed, second case is a parse error
+ SearchLength = (delta >= 0) ? delta : (urlEnd - Search);
Y_ASSERT(strlen(Search) == SearchLength);
- } else {
- SearchLength = 0;
- }
+ } else {
+ SearchLength = 0;
+ }
OrigSearch = {Search, SearchLength};
- return true;
-}
-
+ return true;
+}
+
void TBaseServerRequestData::AddHeader(const TString& name, const TString& value) {
HeadersIn_[name] = value;
-
+
if (stricmp(name.data(), "Host") == 0) {
size_t hostLen = strcspn(value.data(), ":");
if (value[hostLen] == ':')
Port = value.substr(hostLen + 1);
Host = value.substr(0, hostLen);
- }
-}
-
+ }
+}
+
void TBaseServerRequestData::SetPath(const TString& path) {
PathStorage = TBuffer(path.data(), path.size() + 1);
Path = PathStorage.Data();
-}
+}
diff --git a/library/cpp/http/misc/httpreqdata.h b/library/cpp/http/misc/httpreqdata.h
index 946a0e5f14..16e59c4d78 100644
--- a/library/cpp/http/misc/httpreqdata.h
+++ b/library/cpp/http/misc/httpreqdata.h
@@ -1,14 +1,14 @@
#pragma once
#include <library/cpp/digest/lower_case/hash_ops.h>
-
-#include <util/str_stl.h>
-
+
+#include <util/str_stl.h>
+
#include <util/system/defaults.h>
-#include <util/string/cast.h>
+#include <util/string/cast.h>
#include <library/cpp/cgiparam/cgiparam.h>
#include <util/network/address.h>
-#include <util/network/socket.h>
+#include <util/network/socket.h>
#include <util/generic/hash.h>
#include <util/system/yassert.h>
#include <util/generic/string.h>
@@ -21,16 +21,16 @@ class TBaseServerRequestData {
public:
TBaseServerRequestData(SOCKET s = INVALID_SOCKET);
TBaseServerRequestData(const char* qs, SOCKET s = INVALID_SOCKET);
-
+
void SetHost(const TString& host, ui16 port) {
Host = host;
Port = ToString(port);
}
-
+
const TString& ServerName() const {
return Host;
}
-
+
NAddr::IRemoteAddrPtr ServerAddress() const {
return NAddr::GetSockAddr(Socket);
}
@@ -38,57 +38,57 @@ public:
const TString& ServerPort() const {
return Port;
}
-
+
const char* ScriptName() const {
return Path;
}
-
+
const char* QueryString() const {
return Search;
}
-
+
TStringBuf QueryStringBuf() const {
return TStringBuf(Search, SearchLength);
}
-
+
TStringBuf OrigQueryStringBuf() const {
return OrigSearch;
}
- void AppendQueryString(const char* str, size_t length);
- const char* RemoteAddr() const;
+ void AppendQueryString(const char* str, size_t length);
+ const char* RemoteAddr() const;
void SetRemoteAddr(TStringBuf addr);
const char* HeaderIn(TStringBuf key) const;
-
+
const THttpHeadersContainer& HeadersIn() const {
return HeadersIn_;
}
inline size_t HeadersCount() const noexcept {
return HeadersIn_.size();
- }
-
+ }
+
TString HeaderByIndex(size_t n) const noexcept;
- const char* Environment(const char* key) const;
-
- void Clear();
-
+ const char* Environment(const char* key) const;
+
+ void Clear();
+
void SetSocket(SOCKET s) noexcept {
- Socket = s;
- }
-
+ Socket = s;
+ }
+
ui64 RequestBeginTime() const noexcept {
- return BeginTime;
- }
-
+ return BeginTime;
+ }
+
void SetPath(const TString& path);
const char* GetCurPage() const;
bool Parse(const char* req);
void AddHeader(const TString& name, const TString& value);
-
+
private:
TBuffer PathStorage;
- mutable char* Addr;
+ mutable char* Addr;
TString Host;
TString Port;
char* Path;
@@ -98,13 +98,13 @@ private:
THttpHeadersContainer HeadersIn_;
mutable char AddrData[INET6_ADDRSTRLEN];
SOCKET Socket;
- ui64 BeginTime;
+ ui64 BeginTime;
mutable TString CurPage;
TBuffer ParseBuf;
TBuffer ModifiedQueryString;
};
-
-class TServerRequestData: public TBaseServerRequestData {
+
+class TServerRequestData: public TBaseServerRequestData {
public:
TServerRequestData(SOCKET s = INVALID_SOCKET)
: TBaseServerRequestData(s)
@@ -119,7 +119,7 @@ public:
void Scan() {
CgiParam.Scan(QueryStringBuf());
}
-
+
public:
- TCgiParameters CgiParam;
+ TCgiParameters CgiParam;
};
diff --git a/library/cpp/http/misc/httpreqdata_ut.cpp b/library/cpp/http/misc/httpreqdata_ut.cpp
index 24225e78ac..e7f16ef27c 100644
--- a/library/cpp/http/misc/httpreqdata_ut.cpp
+++ b/library/cpp/http/misc/httpreqdata_ut.cpp
@@ -4,19 +4,19 @@
Y_UNIT_TEST_SUITE(TRequestServerDataTest) {
Y_UNIT_TEST(Headers) {
- TServerRequestData sd;
-
+ TServerRequestData sd;
+
sd.AddHeader("x-xx", "y-yy");
sd.AddHeader("x-Xx", "y-yy");
-
- UNIT_ASSERT_VALUES_EQUAL(sd.HeadersCount(), 1);
-
+
+ UNIT_ASSERT_VALUES_EQUAL(sd.HeadersCount(), 1);
+
sd.AddHeader("x-XxX", "y-yyy");
- UNIT_ASSERT_VALUES_EQUAL(sd.HeadersCount(), 2);
+ UNIT_ASSERT_VALUES_EQUAL(sd.HeadersCount(), 2);
UNIT_ASSERT_VALUES_EQUAL(TStringBuf(sd.HeaderIn("X-XX")), TStringBuf("y-yy"));
UNIT_ASSERT_VALUES_EQUAL(TStringBuf(sd.HeaderIn("X-XXX")), TStringBuf("y-yyy"));
- }
-
+ }
+
Y_UNIT_TEST(ComplexHeaders) {
TServerRequestData sd;
sd.SetHost("zzz", 1);
@@ -43,24 +43,24 @@ Y_UNIT_TEST_SUITE(TRequestServerDataTest) {
}
Y_UNIT_TEST(ParseScan) {
- TServerRequestData rd;
+ TServerRequestData rd;
- // Parse parses url without host
- UNIT_ASSERT(!rd.Parse(" http://yandex.ru/yandsearch?&gta=fake&haha=da HTTP 1.1 OK"));
+ // Parse parses url without host
+ UNIT_ASSERT(!rd.Parse(" http://yandex.ru/yandsearch?&gta=fake&haha=da HTTP 1.1 OK"));
- // This should work
- UNIT_ASSERT(rd.Parse(" /yandsearch?&gta=fake&haha=da HTTP 1.1 OK"));
+ // This should work
+ UNIT_ASSERT(rd.Parse(" /yandsearch?&gta=fake&haha=da HTTP 1.1 OK"));
UNIT_ASSERT_STRINGS_EQUAL(rd.QueryStringBuf(), "&gta=fake&haha=da");
UNIT_ASSERT_STRINGS_EQUAL(rd.QueryStringBuf(), rd.OrigQueryStringBuf());
- rd.Scan();
- UNIT_ASSERT(rd.CgiParam.Has("gta", "fake"));
- UNIT_ASSERT(rd.CgiParam.Has("haha", "da"));
- UNIT_ASSERT(!rd.CgiParam.Has("no-param"));
+ rd.Scan();
+ UNIT_ASSERT(rd.CgiParam.Has("gta", "fake"));
+ UNIT_ASSERT(rd.CgiParam.Has("haha", "da"));
+ UNIT_ASSERT(!rd.CgiParam.Has("no-param"));
- rd.Clear();
- }
+ rd.Clear();
+ }
Y_UNIT_TEST(Ctor) {
const TString qs("gta=fake&haha=da");
@@ -69,55 +69,55 @@ Y_UNIT_TEST_SUITE(TRequestServerDataTest) {
UNIT_ASSERT_STRINGS_EQUAL(rd.QueryStringBuf(), qs);
UNIT_ASSERT_STRINGS_EQUAL(rd.OrigQueryStringBuf(), qs);
- UNIT_ASSERT(rd.CgiParam.Has("gta"));
- UNIT_ASSERT(rd.CgiParam.Has("haha"));
- UNIT_ASSERT(!rd.CgiParam.Has("no-param"));
- }
+ UNIT_ASSERT(rd.CgiParam.Has("gta"));
+ UNIT_ASSERT(rd.CgiParam.Has("haha"));
+ UNIT_ASSERT(!rd.CgiParam.Has("no-param"));
+ }
Y_UNIT_TEST(HashCut) {
const TString qs("&gta=fake&haha=da");
const TString header = " /yandsearch?" + qs + "#&uberParam=yes&q=? HTTP 1.1 OK";
- TServerRequestData rd;
+ TServerRequestData rd;
rd.Parse(header.c_str());
UNIT_ASSERT_STRINGS_EQUAL(rd.QueryStringBuf(), qs);
UNIT_ASSERT_STRINGS_EQUAL(rd.OrigQueryStringBuf(), qs);
- rd.Scan();
- UNIT_ASSERT(rd.CgiParam.Has("gta"));
- UNIT_ASSERT(rd.CgiParam.Has("haha"));
- UNIT_ASSERT(!rd.CgiParam.Has("uberParam"));
- }
+ rd.Scan();
+ UNIT_ASSERT(rd.CgiParam.Has("gta"));
+ UNIT_ASSERT(rd.CgiParam.Has("haha"));
+ UNIT_ASSERT(!rd.CgiParam.Has("uberParam"));
+ }
Y_UNIT_TEST(MisplacedHashCut) {
- TServerRequestData rd;
- rd.Parse(" /y#ndsearch?&gta=fake&haha=da&uberParam=yes&q=? HTTP 1.1 OK");
+ TServerRequestData rd;
+ rd.Parse(" /y#ndsearch?&gta=fake&haha=da&uberParam=yes&q=? HTTP 1.1 OK");
UNIT_ASSERT_STRINGS_EQUAL(rd.QueryStringBuf(), "");
UNIT_ASSERT_STRINGS_EQUAL(rd.OrigQueryStringBuf(), "");
- rd.Scan();
- UNIT_ASSERT(rd.CgiParam.empty());
- }
+ rd.Scan();
+ UNIT_ASSERT(rd.CgiParam.empty());
+ }
Y_UNIT_TEST(CornerCase) {
- TServerRequestData rd;
- rd.Parse(" /yandsearch?#");
+ TServerRequestData rd;
+ rd.Parse(" /yandsearch?#");
UNIT_ASSERT_STRINGS_EQUAL(rd.QueryStringBuf(), "");
UNIT_ASSERT_STRINGS_EQUAL(rd.OrigQueryStringBuf(), "");
- rd.Scan();
- UNIT_ASSERT(rd.CgiParam.empty());
- }
+ rd.Scan();
+ UNIT_ASSERT(rd.CgiParam.empty());
+ }
Y_UNIT_TEST(AppendQueryString) {
const TString qs("gta=fake&haha=da");
TServerRequestData rd(qs.c_str());
- UNIT_ASSERT(rd.CgiParam.Has("gta", "fake"));
- UNIT_ASSERT(rd.CgiParam.Has("haha", "da"));
+ UNIT_ASSERT(rd.CgiParam.Has("gta", "fake"));
+ UNIT_ASSERT(rd.CgiParam.Has("haha", "da"));
UNIT_ASSERT_STRINGS_EQUAL(rd.QueryStringBuf(), qs);
UNIT_ASSERT_STRINGS_EQUAL(rd.QueryStringBuf(), rd.OrigQueryStringBuf());
@@ -128,11 +128,11 @@ Y_UNIT_TEST_SUITE(TRequestServerDataTest) {
UNIT_ASSERT_STRINGS_EQUAL(rd.QueryStringBuf(), qs + '&' + appendix);
UNIT_ASSERT_STRINGS_EQUAL(rd.OrigQueryStringBuf(), qs);
- rd.Scan();
+ rd.Scan();
- UNIT_ASSERT(rd.CgiParam.Has("gta", "true"));
- UNIT_ASSERT(rd.CgiParam.Has("gta", "new"));
- }
+ UNIT_ASSERT(rd.CgiParam.Has("gta", "true"));
+ UNIT_ASSERT(rd.CgiParam.Has("gta", "new"));
+ }
Y_UNIT_TEST(SetRemoteAddrSimple) {
static const TString TEST = "abacaba.search.yandex.net";
diff --git a/library/cpp/http/misc/parsed_request.cpp b/library/cpp/http/misc/parsed_request.cpp
index 8568293e2c..e332a24e91 100644
--- a/library/cpp/http/misc/parsed_request.cpp
+++ b/library/cpp/http/misc/parsed_request.cpp
@@ -1,32 +1,32 @@
-#include "parsed_request.h"
-
+#include "parsed_request.h"
+
#include <util/string/strip.h>
-#include <util/generic/yexception.h>
+#include <util/generic/yexception.h>
#include <util/string/cast.h>
-
+
static inline TStringBuf StripLeft(const TStringBuf& s) noexcept {
- const char* b = s.begin();
- const char* e = s.end();
-
- StripRangeBegin(b, e);
-
- return TStringBuf(b, e);
-}
-
-TParsedHttpRequest::TParsedHttpRequest(const TStringBuf& str) {
- TStringBuf tmp;
-
+ const char* b = s.begin();
+ const char* e = s.end();
+
+ StripRangeBegin(b, e);
+
+ return TStringBuf(b, e);
+}
+
+TParsedHttpRequest::TParsedHttpRequest(const TStringBuf& str) {
+ TStringBuf tmp;
+
if (!StripLeft(str).TrySplit(' ', Method, tmp)) {
- ythrow yexception() << "bad request(" << ToString(str).Quote() << ")";
- }
-
+ ythrow yexception() << "bad request(" << ToString(str).Quote() << ")";
+ }
+
if (!StripLeft(tmp).TrySplit(' ', Request, Proto)) {
- ythrow yexception() << "bad request(" << ToString(str).Quote() << ")";
- }
-
- Proto = StripLeft(Proto);
-}
-
-TParsedHttpLocation::TParsedHttpLocation(const TStringBuf& req) {
- req.Split('?', Path, Cgi);
-}
+ ythrow yexception() << "bad request(" << ToString(str).Quote() << ")";
+ }
+
+ Proto = StripLeft(Proto);
+}
+
+TParsedHttpLocation::TParsedHttpLocation(const TStringBuf& req) {
+ req.Split('?', Path, Cgi);
+}
diff --git a/library/cpp/http/misc/parsed_request.h b/library/cpp/http/misc/parsed_request.h
index 00ba7767e7..d4df705495 100644
--- a/library/cpp/http/misc/parsed_request.h
+++ b/library/cpp/http/misc/parsed_request.h
@@ -1,26 +1,26 @@
#pragma once
-
-#include <util/generic/strbuf.h>
-
-struct TParsedHttpRequest {
- TParsedHttpRequest(const TStringBuf& str);
-
- TStringBuf Method;
- TStringBuf Request;
- TStringBuf Proto;
-};
-
-struct TParsedHttpLocation {
- TParsedHttpLocation(const TStringBuf& req);
-
- TStringBuf Path;
- TStringBuf Cgi;
-};
-
-struct TParsedHttpFull: public TParsedHttpRequest, public TParsedHttpLocation {
- inline TParsedHttpFull(const TStringBuf& line)
- : TParsedHttpRequest(line)
- , TParsedHttpLocation(Request)
- {
- }
-};
+
+#include <util/generic/strbuf.h>
+
+struct TParsedHttpRequest {
+ TParsedHttpRequest(const TStringBuf& str);
+
+ TStringBuf Method;
+ TStringBuf Request;
+ TStringBuf Proto;
+};
+
+struct TParsedHttpLocation {
+ TParsedHttpLocation(const TStringBuf& req);
+
+ TStringBuf Path;
+ TStringBuf Cgi;
+};
+
+struct TParsedHttpFull: public TParsedHttpRequest, public TParsedHttpLocation {
+ inline TParsedHttpFull(const TStringBuf& line)
+ : TParsedHttpRequest(line)
+ , TParsedHttpLocation(Request)
+ {
+ }
+};
diff --git a/library/cpp/http/misc/parsed_request_ut.cpp b/library/cpp/http/misc/parsed_request_ut.cpp
index d578f69f24..da6d95c6ab 100644
--- a/library/cpp/http/misc/parsed_request_ut.cpp
+++ b/library/cpp/http/misc/parsed_request_ut.cpp
@@ -1,28 +1,28 @@
-#include "parsed_request.h"
-
+#include "parsed_request.h"
+
#include <library/cpp/testing/unittest/registar.h>
-
+
Y_UNIT_TEST_SUITE(THttpParse) {
Y_UNIT_TEST(TestParse) {
- TParsedHttpFull h("GET /yandsearch?text=nokia HTTP/1.1");
-
- UNIT_ASSERT_EQUAL(h.Method, "GET");
- UNIT_ASSERT_EQUAL(h.Request, "/yandsearch?text=nokia");
- UNIT_ASSERT_EQUAL(h.Proto, "HTTP/1.1");
-
- UNIT_ASSERT_EQUAL(h.Path, "/yandsearch");
- UNIT_ASSERT_EQUAL(h.Cgi, "text=nokia");
- }
-
+ TParsedHttpFull h("GET /yandsearch?text=nokia HTTP/1.1");
+
+ UNIT_ASSERT_EQUAL(h.Method, "GET");
+ UNIT_ASSERT_EQUAL(h.Request, "/yandsearch?text=nokia");
+ UNIT_ASSERT_EQUAL(h.Proto, "HTTP/1.1");
+
+ UNIT_ASSERT_EQUAL(h.Path, "/yandsearch");
+ UNIT_ASSERT_EQUAL(h.Cgi, "text=nokia");
+ }
+
Y_UNIT_TEST(TestError) {
- bool wasError = false;
-
- try {
- TParsedHttpFull("GET /yandsearch?text=nokiaHTTP/1.1");
- } catch (...) {
- wasError = true;
- }
-
- UNIT_ASSERT(wasError);
- }
-}
+ bool wasError = false;
+
+ try {
+ TParsedHttpFull("GET /yandsearch?text=nokiaHTTP/1.1");
+ } catch (...) {
+ wasError = true;
+ }
+
+ UNIT_ASSERT(wasError);
+ }
+}
diff --git a/library/cpp/http/misc/ut/ya.make b/library/cpp/http/misc/ut/ya.make
index 49ca2b9aaf..f4bdd35662 100644
--- a/library/cpp/http/misc/ut/ya.make
+++ b/library/cpp/http/misc/ut/ya.make
@@ -1,11 +1,11 @@
UNITTEST_FOR(library/cpp/http/misc)
-
+
OWNER(g:util)
-
-SRCS(
- httpdate_ut.cpp
- httpreqdata_ut.cpp
- parsed_request_ut.cpp
-)
-
-END()
+
+SRCS(
+ httpdate_ut.cpp
+ httpreqdata_ut.cpp
+ parsed_request_ut.cpp
+)
+
+END()
diff --git a/library/cpp/http/misc/ya.make b/library/cpp/http/misc/ya.make
index 7a0f2a6e9f..fceb3cf79c 100644
--- a/library/cpp/http/misc/ya.make
+++ b/library/cpp/http/misc/ya.make
@@ -1,24 +1,24 @@
-LIBRARY()
-
+LIBRARY()
+
OWNER(
g:util
mvel
)
-
+
GENERATE_ENUM_SERIALIZATION(httpcodes.h)
-SRCS(
- httpcodes.cpp
- httpdate.cpp
- httpreqdata.cpp
- parsed_request.cpp
-)
-
+SRCS(
+ httpcodes.cpp
+ httpdate.cpp
+ httpreqdata.cpp
+ parsed_request.cpp
+)
+
PEERDIR(
library/cpp/cgiparam
library/cpp/digest/lower_case
)
-END()
+END()
RECURSE_FOR_TESTS(ut)
diff --git a/library/cpp/http/server/conn.cpp b/library/cpp/http/server/conn.cpp
index dd0860a315..38a76c4c30 100644
--- a/library/cpp/http/server/conn.cpp
+++ b/library/cpp/http/server/conn.cpp
@@ -1,31 +1,31 @@
-#include "conn.h"
-
-#include <util/network/socket.h>
+#include "conn.h"
+
+#include <util/network/socket.h>
#include <util/stream/buffered.h>
-
-class THttpServerConn::TImpl {
-public:
+
+class THttpServerConn::TImpl {
+public:
inline TImpl(const TSocket& s, size_t outputBufferSize)
- : S_(s)
- , SI_(S_)
- , SO_(S_)
+ : S_(s)
+ , SI_(S_)
+ , SO_(S_)
, BO_(&SO_, outputBufferSize)
- , HI_(&SI_)
- , HO_(&BO_, &HI_)
- {
- }
-
+ , HI_(&SI_)
+ , HO_(&BO_, &HI_)
+ {
+ }
+
inline ~TImpl() {
- }
-
+ }
+
inline THttpInput* Input() noexcept {
- return &HI_;
- }
-
+ return &HI_;
+ }
+
inline THttpOutput* Output() noexcept {
- return &HO_;
- }
-
+ return &HO_;
+ }
+
inline void Reset() {
if (S_ != INVALID_SOCKET) {
// send RST packet to client
@@ -34,35 +34,35 @@ public:
}
}
-private:
- TSocket S_;
- TSocketInput SI_;
- TSocketOutput SO_;
- TBufferedOutput BO_;
- THttpInput HI_;
- THttpOutput HO_;
-};
-
-THttpServerConn::THttpServerConn(const TSocket& s)
+private:
+ TSocket S_;
+ TSocketInput SI_;
+ TSocketOutput SO_;
+ TBufferedOutput BO_;
+ THttpInput HI_;
+ THttpOutput HO_;
+};
+
+THttpServerConn::THttpServerConn(const TSocket& s)
: THttpServerConn(s, s.MaximumTransferUnit())
-{
-}
-
+{
+}
+
THttpServerConn::THttpServerConn(const TSocket& s, size_t outputBufferSize)
: Impl_(new TImpl(s, outputBufferSize))
{
}
THttpServerConn::~THttpServerConn() {
-}
-
+}
+
THttpInput* THttpServerConn::Input() noexcept {
- return Impl_->Input();
-}
-
+ return Impl_->Input();
+}
+
THttpOutput* THttpServerConn::Output() noexcept {
- return Impl_->Output();
-}
+ return Impl_->Output();
+}
void THttpServerConn::Reset() {
return Impl_->Reset();
diff --git a/library/cpp/http/server/conn.h b/library/cpp/http/server/conn.h
index 93c2358c23..3aa5329af4 100644
--- a/library/cpp/http/server/conn.h
+++ b/library/cpp/http/server/conn.h
@@ -1,37 +1,37 @@
-#pragma once
-
+#pragma once
+
#include <library/cpp/http/io/stream.h>
-#include <util/generic/ptr.h>
-
-class TSocket;
-
-/// Потоки ввода/вывода для получения запросов и отправки ответов HTTP-сервера.
-class THttpServerConn {
-public:
- explicit THttpServerConn(const TSocket& s);
- THttpServerConn(const TSocket& s, size_t outputBufferSize);
+#include <util/generic/ptr.h>
+
+class TSocket;
+
+/// Потоки ввода/вывода для получения запросов и отправки ответов HTTP-сервера.
+class THttpServerConn {
+public:
+ explicit THttpServerConn(const TSocket& s);
+ THttpServerConn(const TSocket& s, size_t outputBufferSize);
~THttpServerConn();
-
+
THttpInput* Input() noexcept;
THttpOutput* Output() noexcept;
-
+
inline const THttpInput* Input() const noexcept {
- return const_cast<THttpServerConn*>(this)->Input();
- }
-
+ return const_cast<THttpServerConn*>(this)->Input();
+ }
+
inline const THttpOutput* Output() const noexcept {
- return const_cast<THttpServerConn*>(this)->Output();
- }
-
- /// Проверяет, можно ли установить режим, при котором соединение с сервером
- /// не завершается после окончания транзакции.
+ return const_cast<THttpServerConn*>(this)->Output();
+ }
+
+ /// Проверяет, можно ли установить режим, при котором соединение с сервером
+ /// не завершается после окончания транзакции.
inline bool CanBeKeepAlive() const noexcept {
- return Output()->CanBeKeepAlive();
- }
-
+ return Output()->CanBeKeepAlive();
+ }
+
void Reset();
-private:
- class TImpl;
- THolder<TImpl> Impl_;
-};
+private:
+ class TImpl;
+ THolder<TImpl> Impl_;
+};
diff --git a/library/cpp/http/server/http.cpp b/library/cpp/http/server/http.cpp
index 581fc77399..128583bdd7 100644
--- a/library/cpp/http/server/http.cpp
+++ b/library/cpp/http/server/http.cpp
@@ -1,12 +1,12 @@
#include "http.h"
#include "http_ex.h"
-
+
#include <library/cpp/threading/equeue/equeue.h>
#include <util/generic/buffer.h>
#include <util/generic/cast.h>
-#include <util/generic/intrlist.h>
-#include <util/generic/yexception.h>
+#include <util/generic/intrlist.h>
+#include <util/generic/yexception.h>
#include <util/network/address.h>
#include <util/network/socket.h>
#include <util/network/poller.h>
@@ -18,7 +18,7 @@
#include <util/system/pipe.h>
#include <util/system/thread.h>
#include <util/thread/factory.h>
-
+
#include <cerrno>
#include <cstring>
#include <ctime>
@@ -28,39 +28,39 @@
using namespace NAddr;
-namespace {
- class IPollAble {
- public:
+namespace {
+ class IPollAble {
+ public:
inline IPollAble() noexcept {
- }
-
- virtual ~IPollAble() {
- }
-
+ }
+
+ virtual ~IPollAble() {
+ }
+
virtual void OnPollEvent(TInstant now) = 0;
- };
-
- struct TShouldStop {
- };
+ };
- struct TWakeupPollAble: public IPollAble {
+ struct TShouldStop {
+ };
+
+ struct TWakeupPollAble: public IPollAble {
void OnPollEvent(TInstant) override {
- throw TShouldStop();
- }
- };
-}
-
-class TClientConnection: public IPollAble, public TIntrusiveListItem<TClientConnection> {
+ throw TShouldStop();
+ }
+ };
+}
+
+class TClientConnection: public IPollAble, public TIntrusiveListItem<TClientConnection> {
public:
TClientConnection(const TSocket& s, THttpServer::TImpl* serv, NAddr::IRemoteAddrRef listenerSockAddrRef);
~TClientConnection() override;
-
+
void OnPollEvent(TInstant now) override;
-
+
inline void Activate(TInstant now) noexcept;
inline void DeActivate();
inline void Reject();
-
+
public:
TSocket Socket_;
NAddr::IRemoteAddrRef ListenerSockAddrRef_;
@@ -69,28 +69,28 @@ public:
TInstant LastUsed;
TInstant AcceptMoment;
size_t ReceivedRequests = 0;
-};
-
-class THttpServer::TImpl {
+};
+
+class THttpServer::TImpl {
public:
class TConnections {
- public:
+ public:
inline TConnections(TSocketPoller* poller, const THttpServerOptions& options)
: Poller_(poller)
, Options(options)
{
}
-
+
inline ~TConnections() {
}
-
+
inline void Add(TClientConnection* c) noexcept {
TGuard<TMutex> g(Mutex_);
-
+
Conns_.PushBack(c);
Poller_->WaitRead(c->Socket_, (void*)static_cast<const IPollAble*>(c));
}
-
+
inline void Erase(TClientConnection* c, TInstant now) noexcept {
TGuard<TMutex> g(Mutex_);
EraseUnsafe(c);
@@ -98,18 +98,18 @@ public:
TryRemovingUnsafe(now - Options.ExpirationTimeout);
}
}
-
+
inline void Clear() noexcept {
TGuard<TMutex> g(Mutex_);
-
+
Conns_.Clear();
}
-
+
inline bool RemoveOld(TInstant border) noexcept {
TGuard<TMutex> g(Mutex_);
return TryRemovingUnsafe(border);
}
-
+
bool TryRemovingUnsafe(TInstant border) noexcept {
if (Conns_.Empty()) {
return false;
@@ -122,7 +122,7 @@ public:
delete c;
return true;
}
-
+
void EraseUnsafe(TClientConnection* c) noexcept {
Poller_->Unwait(c->Socket_);
c->Unlink();
@@ -134,7 +134,7 @@ public:
TSocketPoller* Poller_ = nullptr;
const THttpServerOptions& Options;
};
-
+
static void* ListenSocketFunction(void* param) {
try {
((TImpl*)param)->ListenSocket();
@@ -144,10 +144,10 @@ public:
return nullptr;
}
-
+
TAutoPtr<TClientRequest> CreateRequest(TAutoPtr<TClientConnection> c) {
THolder<TClientRequest> obj(Cb_->CreateClient());
-
+
obj->Conn_.Reset(c.Release());
return obj;
@@ -161,13 +161,13 @@ public:
(new TClientConnection(s, this, listenerSockAddrRef))->Reject();
return;
}
- }
-
+ }
+
auto connection = new TClientConnection(s, this, listenerSockAddrRef);
connection->LastUsed = now;
connection->DeActivate();
}
-
+
void SaveErrorCode() {
ErrorCode = WSAGetLastError();
}
@@ -175,11 +175,11 @@ public:
int GetErrorCode() const {
return ErrorCode;
}
-
+
const char* GetError() const {
return LastSystemErrorText(ErrorCode);
}
-
+
bool Start() {
Poller.Reset(new TSocketPoller());
Connections.Reset(new TConnections(Poller.Get(), Options_));
@@ -202,14 +202,14 @@ public:
} catch (const yexception&) {
SaveErrorCode();
return false;
- }
-
+ }
+
// Wait until the thread has completely started and return the success indicator
ListenStartEvent.Wait();
-
+
return ListenerRunningOK;
}
-
+
void Wait() {
Cb_->OnWait();
TGuard<TMutex> g(StopMutex);
@@ -227,46 +227,46 @@ public:
ListenThread->Join();
ListenThread.Reset(nullptr);
}
-
+
while (ConnectionCount) {
usleep(10000);
Connections->Clear();
- }
-
+ }
+
Connections.Destroy();
Poller.Destroy();
}
-
+
void Shutdown() {
ListenWakeupWriteFd.Write("", 1);
// ignore result
}
-
+
void AddRequest(TAutoPtr<TClientRequest> req, bool fail) {
struct TFailRequest: public THttpClientRequestEx {
- inline TFailRequest(TAutoPtr<TClientRequest> parent) {
- Conn_.Reset(parent->Conn_.Release());
- HttpConn_.Reset(parent->HttpConn_.Release());
- }
-
+ inline TFailRequest(TAutoPtr<TClientRequest> parent) {
+ Conn_.Reset(parent->Conn_.Release());
+ HttpConn_.Reset(parent->HttpConn_.Release());
+ }
+
bool Reply(void*) override {
if (!ProcessHeaders()) {
return true;
}
- ProcessFailRequest(0);
- return true;
- }
+ ProcessFailRequest(0);
+ return true;
+ }
};
-
+
if (!fail && Requests->Add(req.Get())) {
Y_UNUSED(req.Release());
} else {
req = new TFailRequest(req);
-
+
if (FailRequests->Add(req.Get())) {
Y_UNUSED(req.Release());
- } else {
+ } else {
Cb_->OnFailRequest(-1);
}
}
@@ -288,44 +288,44 @@ public:
return *FailRequests;
}
- class TListenSocket: public IPollAble, public TIntrusiveListItem<TListenSocket> {
- public:
- inline TListenSocket(const TSocket& s, TImpl* parent)
- : S_(s)
- , Server_(parent)
+ class TListenSocket: public IPollAble, public TIntrusiveListItem<TListenSocket> {
+ public:
+ inline TListenSocket(const TSocket& s, TImpl* parent)
+ : S_(s)
+ , Server_(parent)
, SockAddrRef_(GetSockAddr(S_))
- {
- }
-
+ {
+ }
+
~TListenSocket() override {
- }
-
+ }
+
void OnPollEvent(TInstant) override {
SOCKET s = ::accept(S_, nullptr, nullptr);
-
- if (s == INVALID_SOCKET) {
- ythrow yexception() << "accept: " << LastSystemErrorText();
+
+ if (s == INVALID_SOCKET) {
+ ythrow yexception() << "accept: " << LastSystemErrorText();
}
Server_->AddRequestFromSocket(s, TInstant::Now(), SockAddrRef_);
- }
+ }
SOCKET GetSocket() const noexcept {
- return S_;
- }
-
- private:
- TSocket S_;
+ return S_;
+ }
+
+ private:
+ TSocket S_;
TImpl* Server_ = nullptr;
NAddr::IRemoteAddrRef SockAddrRef_;
};
-
+
void ListenSocket() {
TThread::SetCurrentThreadName(Options_.ListenThreadName.c_str());
ErrorCode = 0;
TIntrusiveListWithAutoDelete<TListenSocket, TDelete> Reqs;
-
+
std::function<void(TSocket)> callback = [&](TSocket socket) {
THolder<TListenSocket> ls(new TListenSocket(socket, this));
Poller->WaitRead(socket, static_cast<IPollAble*>(ls.Get()));
@@ -335,7 +335,7 @@ public:
if (!addressesBound) {
SaveErrorCode();
ListenStartEvent.Signal();
-
+
return;
}
@@ -347,18 +347,18 @@ public:
TVector<void*> events;
events.resize(1);
-
+
TInstant now = TInstant::Now();
- for (;;) {
+ for (;;) {
try {
const TInstant deadline = Options_.PollTimeout == TDuration::Zero() ? TInstant::Max() : now + Options_.PollTimeout;
const size_t ret = Poller->WaitD(events.data(), events.size(), deadline);
-
+
now = TInstant::Now();
for (size_t i = 0; i < ret; ++i) {
((IPollAble*)events[i])->OnPollEvent(now);
}
-
+
if (ret == 0 && Options_.ExpirationTimeout > TDuration::Zero()) {
Connections->RemoveOld(now - Options_.ExpirationTimeout);
}
@@ -370,26 +370,26 @@ public:
if (!Options_.MaxConnections && Options_.ExpirationTimeout == TDuration::Zero()) {
if (ret >= events.size()) {
events.resize(ret * 2);
- }
- }
- } catch (const TShouldStop&) {
- break;
+ }
+ }
+ } catch (const TShouldStop&) {
+ break;
} catch (...) {
Cb_->OnException();
- }
- }
+ }
+ }
while (!Reqs.Empty()) {
THolder<TListenSocket> ls(Reqs.PopFront());
-
+
Poller->Unwait(ls->GetSocket());
- }
-
+ }
+
Requests->Stop();
FailRequests->Stop();
Cb_->OnListenStop();
}
-
+
void RestartRequestThreads(ui32 nTh, ui32 maxQS) {
Requests->Stop();
Options_.nThreads = nTh;
@@ -408,24 +408,24 @@ public:
TImpl(THttpServer* parent, ICallBack* cb, const TOptions& options, IThreadFactory* factory)
: TImpl(
- parent,
- cb,
+ parent,
+ cb,
MakeThreadPool<TSimpleThreadPool>(factory, options.UseElasticQueues, cb, options.RequestsThreadName),
MakeThreadPool<TThreadPool>(factory, options.UseElasticQueues, nullptr, options.FailRequestsThreadName),
- options) {
+ options) {
}
~TImpl() {
try {
Stop();
} catch (...) {
- }
+ }
}
-
+
inline const TOptions& Options() const noexcept {
return Options_;
}
-
+
inline void DecreaseConnections() noexcept {
AtomicDecrement(ConnectionCount);
}
@@ -439,7 +439,7 @@ public:
}
inline bool MaxRequestsReached() const {
- return Options_.MaxConnections && ((size_t)GetClientCount() >= Options_.MaxConnections);
+ return Options_.MaxConnections && ((size_t)GetClientCount() >= Options_.MaxConnections);
}
THolder<TThread> ListenThread;
@@ -480,57 +480,57 @@ private:
return pool;
}
-};
+};
THttpServer::THttpServer(ICallBack* cb, const TOptions& options, IThreadFactory* pool)
: Impl_(new TImpl(this, cb, options, pool))
-{
-}
-
+{
+}
+
THttpServer::THttpServer(ICallBack* cb, TMtpQueueRef mainWorkers, TMtpQueueRef failWorkers, const TOptions& options)
: Impl_(new TImpl(this, cb, mainWorkers, failWorkers, options))
{
}
-THttpServer::~THttpServer() {
-}
-
+THttpServer::~THttpServer() {
+}
+
i64 THttpServer::GetClientCount() const {
return Impl_->GetClientCount();
}
-bool THttpServer::Start() {
- return Impl_->Start();
-}
-
-void THttpServer::Stop() {
- Impl_->Stop();
-}
-
-void THttpServer::Shutdown() {
- Impl_->Shutdown();
-}
-
-void THttpServer::Wait() {
- Impl_->Wait();
-}
-
-int THttpServer::GetErrorCode() {
- return Impl_->GetErrorCode();
-}
-
-const char* THttpServer::GetError() {
- return Impl_->GetError();
-}
-
-void THttpServer::RestartRequestThreads(ui32 n, ui32 queue) {
- Impl_->RestartRequestThreads(n, queue);
-}
-
+bool THttpServer::Start() {
+ return Impl_->Start();
+}
+
+void THttpServer::Stop() {
+ Impl_->Stop();
+}
+
+void THttpServer::Shutdown() {
+ Impl_->Shutdown();
+}
+
+void THttpServer::Wait() {
+ Impl_->Wait();
+}
+
+int THttpServer::GetErrorCode() {
+ return Impl_->GetErrorCode();
+}
+
+const char* THttpServer::GetError() {
+ return Impl_->GetError();
+}
+
+void THttpServer::RestartRequestThreads(ui32 n, ui32 queue) {
+ Impl_->RestartRequestThreads(n, queue);
+}
+
const THttpServer::TOptions& THttpServer::Options() const noexcept {
- return Impl_->Options();
-}
-
+ return Impl_->Options();
+}
+
size_t THttpServer::GetRequestQueueSize() const {
return Impl_->GetRequestQueueSize();
}
@@ -552,45 +552,45 @@ bool THttpServer::MaxRequestsReached() const {
}
TClientConnection::TClientConnection(const TSocket& s, THttpServer::TImpl* serv, NAddr::IRemoteAddrRef listenerSockAddrRef)
- : Socket_(s)
+ : Socket_(s)
, ListenerSockAddrRef_(listenerSockAddrRef)
- , HttpServ_(serv)
-{
- SetNoDelay(Socket_, true);
-
+ , HttpServ_(serv)
+{
+ SetNoDelay(Socket_, true);
+
const TDuration& clientTimeout = HttpServ_->Options().ClientTimeout;
if (clientTimeout != TDuration::Zero()) {
SetSocketTimeout(Socket_, (long)clientTimeout.Seconds(), clientTimeout.MilliSecondsOfSecond());
}
- HttpServ_->IncreaseConnections();
-}
-
+ HttpServ_->IncreaseConnections();
+}
+
TClientConnection::~TClientConnection() {
- HttpServ_->DecreaseConnections();
-}
-
+ HttpServ_->DecreaseConnections();
+}
+
void TClientConnection::OnPollEvent(TInstant now) {
THolder<TClientConnection> this_(this);
Activate(now);
-
- {
- char tmp[1];
-
- if (::recv(Socket_, tmp, 1, MSG_PEEK) < 1) {
- /*
- * We can received a FIN so our socket was moved to
- * TCP_CLOSE_WAIT state. Check it before adding work
- * for this socket.
- */
-
- return;
- }
- }
-
+
+ {
+ char tmp[1];
+
+ if (::recv(Socket_, tmp, 1, MSG_PEEK) < 1) {
+ /*
+ * We can received a FIN so our socket was moved to
+ * TCP_CLOSE_WAIT state. Check it before adding work
+ * for this socket.
+ */
+
+ return;
+ }
+ }
+
THolder<TClientRequest> obj(HttpServ_->CreateRequest(this_));
AcceptMoment = now;
-
+
HttpServ_->AddRequest(obj, Reject_);
}
@@ -600,35 +600,35 @@ void TClientConnection::Activate(TInstant now) noexcept {
++ReceivedRequests;
}
-void TClientConnection::DeActivate() {
+void TClientConnection::DeActivate() {
HttpServ_->Connections->Add(this);
-}
-
+}
+
void TClientConnection::Reject() {
Reject_ = true;
HttpServ_->Connections->Add(this);
}
-TClientRequest::TClientRequest() {
-}
-
-TClientRequest::~TClientRequest() {
-}
-
-bool TClientRequest::Reply(void* /*ThreadSpecificResource*/) {
+TClientRequest::TClientRequest() {
+}
+
+TClientRequest::~TClientRequest() {
+}
+
+bool TClientRequest::Reply(void* /*ThreadSpecificResource*/) {
if (strnicmp(RequestString.data(), "GET ", 4)) {
- Output() << "HTTP/1.0 501 Not Implemented\r\n\r\n";
- } else {
- Output() << "HTTP/1.0 200 OK\r\n"
- "Content-Type: text/html\r\n"
- "\r\n"
- "Hello World!\r\n";
- }
-
- return true;
-}
-
+ Output() << "HTTP/1.0 501 Not Implemented\r\n\r\n";
+ } else {
+ Output() << "HTTP/1.0 200 OK\r\n"
+ "Content-Type: text/html\r\n"
+ "\r\n"
+ "Hello World!\r\n";
+ }
+
+ return true;
+}
+
bool TClientRequest::IsLocal() const {
return HasLocalAddress(Socket());
}
@@ -639,29 +639,29 @@ bool TClientRequest::CheckLoopback() {
try {
isLocal = IsLocal();
} catch (const yexception& e) {
- Output() << "HTTP/1.0 500 Oops\r\n\r\n"
- << e.what() << "\r\n";
- return false;
+ Output() << "HTTP/1.0 500 Oops\r\n\r\n"
+ << e.what() << "\r\n";
+ return false;
}
if (!isLocal) {
- Output() << "HTTP/1.0 403 Permission denied\r\n"
- "Content-Type: text/html; charset=windows-1251\r\n"
- "Connection: close\r\n"
- "\r\n"
- "<html><head><title>Permission denied</title></head>"
- "<body><h1>Permission denied</h1>"
- "<p>This request must be sent from the localhost.</p>"
- "</body></html>\r\n";
-
- return false;
- }
-
- return true;
-}
-
+ Output() << "HTTP/1.0 403 Permission denied\r\n"
+ "Content-Type: text/html; charset=windows-1251\r\n"
+ "Connection: close\r\n"
+ "\r\n"
+ "<html><head><title>Permission denied</title></head>"
+ "<body><h1>Permission denied</h1>"
+ "<p>This request must be sent from the localhost.</p>"
+ "</body></html>\r\n";
+
+ return false;
+ }
+
+ return true;
+}
+
void TClientRequest::ReleaseConnection() {
- if (Conn_ && HttpConn_ && HttpServ()->Options().KeepAliveEnabled && HttpConn_->CanBeKeepAlive() && (!HttpServ()->Options().RejectExcessConnections || !HttpServ()->MaxRequestsReached())) {
+ if (Conn_ && HttpConn_ && HttpServ()->Options().KeepAliveEnabled && HttpConn_->CanBeKeepAlive() && (!HttpServ()->Options().RejectExcessConnections || !HttpServ()->MaxRequestsReached())) {
Output().Finish();
Conn_->DeActivate();
Y_UNUSED(Conn_.Release());
@@ -676,101 +676,101 @@ void TClientRequest::ResetConnection() {
}
}
-void TClientRequest::Process(void* ThreadSpecificResource) {
+void TClientRequest::Process(void* ThreadSpecificResource) {
THolder<TClientRequest> this_(this);
-
+
auto* serverImpl = Conn_->HttpServ_;
- try {
- if (!HttpConn_) {
+ try {
+ if (!HttpConn_) {
const size_t outputBufferSize = HttpServ()->Options().OutputBufferSize;
if (outputBufferSize) {
HttpConn_.Reset(new THttpServerConn(Socket(), outputBufferSize));
} else {
HttpConn_.Reset(new THttpServerConn(Socket()));
}
-
+
auto maxRequestsPerConnection = HttpServ()->Options().MaxRequestsPerConnection;
HttpConn_->Output()->EnableKeepAlive(HttpServ()->Options().KeepAliveEnabled && (!maxRequestsPerConnection || Conn_->ReceivedRequests < maxRequestsPerConnection));
- HttpConn_->Output()->EnableCompression(HttpServ()->Options().CompressionEnabled);
- }
-
+ HttpConn_->Output()->EnableCompression(HttpServ()->Options().CompressionEnabled);
+ }
+
if (ParsedHeaders.empty()) {
RequestString = Input().FirstLine();
-
- const THttpHeaders& h = Input().Headers();
+
+ const THttpHeaders& h = Input().Headers();
ParsedHeaders.reserve(h.Count());
- for (THttpHeaders::TConstIterator it = h.Begin(); it != h.End(); ++it) {
+ for (THttpHeaders::TConstIterator it = h.Begin(); it != h.End(); ++it) {
ParsedHeaders.emplace_back(it->Name(), it->Value());
- }
- }
-
- if (Reply(ThreadSpecificResource)) {
+ }
+ }
+
+ if (Reply(ThreadSpecificResource)) {
ReleaseConnection();
-
- /*
- * *this will be destroyed...
- */
-
- return;
- }
- } catch (...) {
+
+ /*
+ * *this will be destroyed...
+ */
+
+ return;
+ }
+ } catch (...) {
serverImpl->Cb_->OnException();
-
- throw;
- }
-
+
+ throw;
+ }
+
Y_UNUSED(this_.Release());
-}
-
-void TClientRequest::ProcessFailRequest(int failstate) {
+}
+
+void TClientRequest::ProcessFailRequest(int failstate) {
Output() << "HTTP/1.1 503 Service Unavailable\r\n"
"Content-Type: text/plain\r\n"
"Content-Length: 21\r\n"
"\r\n"
"Service Unavailable\r\n";
-
+
TString url;
-
+
if (!strnicmp(RequestString.data(), "GET ", 4)) {
- // Trying to extract url...
+ // Trying to extract url...
const char* str = RequestString.data();
-
- // Skipping spaces before url...
- size_t start = 3;
+
+ // Skipping spaces before url...
+ size_t start = 3;
while (str[start] == ' ') {
- ++start;
- }
-
- if (str[start]) {
- // Traversing url...
- size_t idx = start;
-
- while (str[idx] != ' ' && str[idx]) {
- ++idx;
- }
-
+ ++start;
+ }
+
+ if (str[start]) {
+ // Traversing url...
+ size_t idx = start;
+
+ while (str[idx] != ' ' && str[idx]) {
+ ++idx;
+ }
+
url = RequestString.substr(start, idx - start);
- }
- }
-
- const THttpServer::ICallBack::TFailLogData d = {
- failstate,
- url,
- };
-
- // Handling failure...
- Conn_->HttpServ_->Cb_->OnFailRequestEx(d);
- Output().Flush();
-}
-
+ }
+ }
+
+ const THttpServer::ICallBack::TFailLogData d = {
+ failstate,
+ url,
+ };
+
+ // Handling failure...
+ Conn_->HttpServ_->Cb_->OnFailRequestEx(d);
+ Output().Flush();
+}
+
THttpServer* TClientRequest::HttpServ() const noexcept {
- return Conn_->HttpServ_->Parent_;
-}
-
+ return Conn_->HttpServ_->Parent_;
+}
+
const TSocket& TClientRequest::Socket() const noexcept {
- return Conn_->Socket_;
-}
+ return Conn_->Socket_;
+}
NAddr::IRemoteAddrRef TClientRequest::GetListenerSockAddrRef() const noexcept {
return Conn_->ListenerSockAddrRef_;
@@ -791,8 +791,8 @@ TRequestReplier::~TRequestReplier() {
bool TRequestReplier::Reply(void* threadSpecificResource) {
const TReplyParams params = {
- threadSpecificResource, Input(), Output()};
-
+ threadSpecificResource, Input(), Output()};
+
return DoReply(params);
}
@@ -833,7 +833,7 @@ bool TryToBindAddresses(const THttpServerOptions& options, const std::function<v
return false;
}
- if (callbackOnBoundAddress != nullptr) {
+ if (callbackOnBoundAddress != nullptr) {
(*callbackOnBoundAddress)(socket);
}
}
diff --git a/library/cpp/http/server/http.h b/library/cpp/http/server/http.h
index 1b72215706..b292d38f27 100644
--- a/library/cpp/http/server/http.h
+++ b/library/cpp/http/server/http.h
@@ -1,92 +1,92 @@
#pragma once
-#include "conn.h"
-#include "options.h"
-
+#include "conn.h"
+#include "options.h"
+
#include <util/thread/pool.h>
#include <library/cpp/http/io/stream.h>
-#include <util/memory/blob.h>
+#include <util/memory/blob.h>
#include <util/generic/ptr.h>
#include <util/generic/vector.h>
#include <util/system/atomic.h>
-
+
class IThreadFactory;
-class TClientRequest;
-class TClientConnection;
+class TClientRequest;
+class TClientConnection;
-class THttpServer {
+class THttpServer {
friend class TClientRequest;
friend class TClientConnection;
-
+
public:
class ICallBack {
- public:
+ public:
struct TFailLogData {
int failstate;
TString url;
};
-
+
virtual ~ICallBack() {
}
-
+
virtual void OnFailRequest(int /*failstate*/) {
}
-
+
virtual void OnFailRequestEx(const TFailLogData& d) {
OnFailRequest(d.failstate);
}
-
+
virtual void OnException() {
}
-
+
virtual void OnMaxConn() {
}
-
+
virtual TClientRequest* CreateClient() = 0;
-
+
virtual void OnListenStart() {
}
-
+
virtual void OnListenStop() {
}
-
+
virtual void OnWait() {
}
-
- virtual void* CreateThreadSpecificResource() {
+
+ virtual void* CreateThreadSpecificResource() {
return nullptr;
}
-
+
virtual void DestroyThreadSpecificResource(void*) {
}
};
-
+
typedef THttpServerOptions TOptions;
typedef TSimpleSharedPtr<IThreadPool> TMtpQueueRef;
-
+
THttpServer(ICallBack* cb, const TOptions& options = TOptions(), IThreadFactory* pool = nullptr);
THttpServer(ICallBack* cb, TMtpQueueRef mainWorkers, TMtpQueueRef failWorkers, const TOptions& options = TOptions());
virtual ~THttpServer();
-
+
bool Start();
-
+
// shutdown a.s.a.p.
void Stop();
-
+
// graceful shutdown with serving all already open connections
void Shutdown();
-
+
void Wait();
int GetErrorCode();
const char* GetError();
void RestartRequestThreads(ui32 nTh, ui32 maxQS);
const TOptions& Options() const noexcept;
i64 GetClientCount() const;
-
+
class TImpl;
size_t GetRequestQueueSize() const;
size_t GetFailQueueSize() const;
-
+
const IThreadPool& GetRequestQueue() const;
const IThreadPool& GetFailQueue() const;
@@ -102,32 +102,32 @@ private:
/**
* @deprecated Use TRequestReplier instead
*/
-class TClientRequest: public IObjectInQueue {
+class TClientRequest: public IObjectInQueue {
friend class THttpServer::TImpl;
-
+
public:
TClientRequest();
~TClientRequest() override;
-
+
inline THttpInput& Input() noexcept {
return *HttpConn_->Input();
}
-
+
inline THttpOutput& Output() noexcept {
return *HttpConn_->Output();
}
-
+
THttpServer* HttpServ() const noexcept;
const TSocket& Socket() const noexcept;
NAddr::IRemoteAddrRef GetListenerSockAddrRef() const noexcept;
TInstant AcceptMoment() const noexcept;
-
+
bool IsLocal() const;
bool CheckLoopback();
void ProcessFailRequest(int failstate);
-
+
void ReleaseConnection();
-
+
void ResetConnection();
private:
@@ -138,17 +138,17 @@ private:
*/
virtual bool Reply(void* ThreadSpecificResource);
void Process(void* ThreadSpecificResource) override;
-
+
public:
TVector<std::pair<TString, TString>> ParsedHeaders;
TString RequestString;
-
+
private:
THolder<TClientConnection> Conn_;
THolder<THttpServerConn> HttpConn_;
-};
-
-class TRequestReplier: public TClientRequest {
+};
+
+class TRequestReplier: public TClientRequest {
public:
TRequestReplier();
~TRequestReplier() override;
diff --git a/library/cpp/http/server/http_ex.cpp b/library/cpp/http/server/http_ex.cpp
index 2fa2ccfead..e07db22bfc 100644
--- a/library/cpp/http/server/http_ex.cpp
+++ b/library/cpp/http/server/http_ex.cpp
@@ -1,32 +1,32 @@
-#include "http_ex.h"
-
-#include <util/generic/buffer.h>
-#include <util/generic/cast.h>
+#include "http_ex.h"
+
+#include <util/generic/buffer.h>
+#include <util/generic/cast.h>
#include <util/stream/null.h>
-
+
bool THttpClientRequestExtension::Parse(char* req, TBaseServerRequestData& rd) {
rd.SetSocket(Socket());
-
+
if (!rd.Parse(req)) {
- Output() << "HTTP/1.1 403 Forbidden\r\n"
- "Content-Type: text/plain\r\n"
- "Content-Length: 39\r\n"
- "\r\n"
- "The server cannot be used as a proxy.\r\n";
-
- return false;
- }
-
- return true;
-}
-
+ Output() << "HTTP/1.1 403 Forbidden\r\n"
+ "Content-Type: text/plain\r\n"
+ "Content-Length: 39\r\n"
+ "\r\n"
+ "The server cannot be used as a proxy.\r\n";
+
+ return false;
+ }
+
+ return true;
+}
+
bool THttpClientRequestExtension::ProcessHeaders(TBaseServerRequestData& rd, TBlob& postData) {
- for (const auto& header : ParsedHeaders) {
+ for (const auto& header : ParsedHeaders) {
rd.AddHeader(header.first, header.second);
- }
-
+ }
+
char* s = RequestString.begin();
-
+
enum EMethod {
NotImplemented,
Get,
@@ -39,7 +39,7 @@ bool THttpClientRequestExtension::ProcessHeaders(TBaseServerRequestData& rd, TBl
enum EMethod foundMethod;
char* urlStart;
- if (strnicmp(s, "GET ", 4) == 0) {
+ if (strnicmp(s, "GET ", 4) == 0) {
foundMethod = Get;
urlStart = s + 4;
} else if (strnicmp(s, "POST ", 5) == 0) {
@@ -59,49 +59,49 @@ bool THttpClientRequestExtension::ProcessHeaders(TBaseServerRequestData& rd, TBl
}
switch (foundMethod) {
- case Get:
- case Delete:
- if (!Parse(urlStart, rd)) {
- return false;
- }
- break;
-
- case Post:
- case Put:
+ case Get:
+ case Delete:
+ if (!Parse(urlStart, rd)) {
+ return false;
+ }
+ break;
+
+ case Post:
+ case Put:
case Patch:
- try {
- ui64 contentLength = 0;
- if (Input().HasExpect100Continue()) {
- Output().SendContinue();
- }
-
- if (!Input().ContentEncoded() && Input().GetContentLength(contentLength)) {
+ try {
+ ui64 contentLength = 0;
+ if (Input().HasExpect100Continue()) {
+ Output().SendContinue();
+ }
+
+ if (!Input().ContentEncoded() && Input().GetContentLength(contentLength)) {
if (contentLength > HttpServ()->Options().MaxInputContentLength) {
Output() << "HTTP/1.1 413 Payload Too Large\r\nContent-Length:0\r\n\r\n";
Output().Finish();
return false;
}
- TBuffer buf(SafeIntegerCast<size_t>(contentLength));
- buf.Resize(Input().Load(buf.Data(), (size_t)contentLength));
- postData = TBlob::FromBuffer(buf);
- } else {
- postData = TBlob::FromStream(Input());
- }
- } catch (...) {
- Output() << "HTTP/1.1 400 Bad request\r\n\r\n";
- return false;
+ TBuffer buf(SafeIntegerCast<size_t>(contentLength));
+ buf.Resize(Input().Load(buf.Data(), (size_t)contentLength));
+ postData = TBlob::FromBuffer(buf);
+ } else {
+ postData = TBlob::FromStream(Input());
+ }
+ } catch (...) {
+ Output() << "HTTP/1.1 400 Bad request\r\n\r\n";
+ return false;
}
- if (!Parse(urlStart, rd)) {
- return false;
- }
- break;
-
- case NotImplemented:
- Output() << "HTTP/1.1 501 Not Implemented\r\n\r\n";
- return false;
- }
-
- return true;
-}
+ if (!Parse(urlStart, rd)) {
+ return false;
+ }
+ break;
+
+ case NotImplemented:
+ Output() << "HTTP/1.1 501 Not Implemented\r\n\r\n";
+ return false;
+ }
+
+ return true;
+}
diff --git a/library/cpp/http/server/http_ex.h b/library/cpp/http/server/http_ex.h
index 39cfbbe66f..1ef43ea4fd 100644
--- a/library/cpp/http/server/http_ex.h
+++ b/library/cpp/http/server/http_ex.h
@@ -1,28 +1,28 @@
-#pragma once
-
-#include "http.h"
-
+#pragma once
+
+#include "http.h"
+
#include <library/cpp/http/misc/httpreqdata.h>
-
-class THttpClientRequestExtension: public TClientRequest {
+
+class THttpClientRequestExtension: public TClientRequest {
public:
bool Parse(char* req, TBaseServerRequestData& rd);
bool ProcessHeaders(TBaseServerRequestData& rd, TBlob& postData);
};
-
+
template <class TRequestData>
-class THttpClientRequestExtImpl: public THttpClientRequestExtension {
-protected:
+class THttpClientRequestExtImpl: public THttpClientRequestExtension {
+protected:
bool Parse(char* req) {
return THttpClientRequestExtension::Parse(req, RD);
}
bool ProcessHeaders() {
return THttpClientRequestExtension::ProcessHeaders(RD, Buf);
}
-
+
protected:
TRequestData RD;
- TBlob Buf;
-};
+ TBlob Buf;
+};
using THttpClientRequestEx = THttpClientRequestExtImpl<TServerRequestData>;
diff --git a/library/cpp/http/server/http_ut.cpp b/library/cpp/http/server/http_ut.cpp
index ab24207eac..cc62bb988e 100644
--- a/library/cpp/http/server/http_ut.cpp
+++ b/library/cpp/http/server/http_ut.cpp
@@ -1,58 +1,58 @@
-#include "http.h"
-#include "http_ex.h"
-
+#include "http.h"
+#include "http_ex.h"
+
#include <library/cpp/testing/unittest/registar.h>
#include <library/cpp/testing/unittest/tests_data.h>
-
+
#include <util/generic/cast.h>
#include <util/stream/output.h>
#include <util/stream/zlib.h>
#include <util/system/datetime.h>
#include <util/system/sem.h>
-
+
Y_UNIT_TEST_SUITE(THttpServerTest) {
- class TEchoServer: public THttpServer::ICallBack {
+ class TEchoServer: public THttpServer::ICallBack {
class TRequest: public THttpClientRequestEx {
- public:
- inline TRequest(TEchoServer* parent)
- : Parent_(parent)
- {
- }
-
+ public:
+ inline TRequest(TEchoServer* parent)
+ : Parent_(parent)
+ {
+ }
+
bool Reply(void* /*tsr*/) override {
- if (!ProcessHeaders()) {
+ if (!ProcessHeaders()) {
return true;
- }
-
- Output() << "HTTP/1.1 200 Ok\r\n\r\n";
+ }
+
+ Output() << "HTTP/1.1 200 Ok\r\n\r\n";
if (Buf.Size()) {
Output().Write(Buf.AsCharPtr(), Buf.Size());
- } else {
- Output() << Parent_->Res_;
- }
- Output().Finish();
-
- return true;
- }
-
- private:
+ } else {
+ Output() << Parent_->Res_;
+ }
+ Output().Finish();
+
+ return true;
+ }
+
+ private:
TEchoServer* Parent_ = nullptr;
- };
-
- public:
+ };
+
+ public:
inline TEchoServer(const TString& res)
- : Res_(res)
- {
- }
-
+ : Res_(res)
+ {
+ }
+
TClientRequest* CreateClient() override {
- return new TRequest(this);
- }
-
- private:
+ return new TRequest(this);
+ }
+
+ private:
TString Res_;
- };
-
+ };
+
class TSleepingServer: public THttpServer::ICallBack {
class TReplier: public TRequestReplier {
public:
@@ -269,7 +269,7 @@ Y_UNIT_TEST_SUITE(THttpServerTest) {
TStringStream ss;
ss << (KeepAliveConnection ? "keep-alive " : "") << Type;
if (ContentEncoding.size()) {
- ss << " with encoding=" << ContentEncoding;
+ ss << " with encoding=" << ContentEncoding;
}
return ss.Str();
} else {
@@ -292,7 +292,7 @@ Y_UNIT_TEST_SUITE(THttpServerTest) {
class TFailingMtpQueue: public TSimpleThreadPool {
private:
bool FailOnAdd_ = false;
-
+
public:
void SetFailOnAdd(bool fail = true) {
FailOnAdd_ = fail;
@@ -313,47 +313,47 @@ Y_UNIT_TEST_SUITE(THttpServerTest) {
TString TestData(size_t size = 5 * 4096) {
TString res;
-
+
for (size_t i = 0; i < size; ++i) {
- res += (char)i;
- }
+ res += (char)i;
+ }
return res;
}
-
+
Y_UNIT_TEST(TestEchoServer) {
TString res = TestData();
TPortManager pm;
const ui16 port = pm.GetPort();
const bool trueFalse[] = {true, false};
-
- TEchoServer serverImpl(res);
- THttpServer server(&serverImpl, THttpServer::TOptions(port).EnableKeepAlive(true).EnableCompression(true));
-
+
+ TEchoServer serverImpl(res);
+ THttpServer server(&serverImpl, THttpServer::TOptions(port).EnableKeepAlive(true).EnableCompression(true));
+
for (int i = 0; i < 2; ++i) {
UNIT_ASSERT(server.Start());
-
+
TTestRequest r(port);
r.Content = res;
-
- for (bool keepAlive : trueFalse) {
+
+ for (bool keepAlive : trueFalse) {
r.KeepAliveConnection = keepAlive;
-
+
// THttpOutput use chunked stream, else use Content-Length
- for (bool useHttpOutput : trueFalse) {
+ for (bool useHttpOutput : trueFalse) {
r.UseHttpOutput = useHttpOutput;
-
- for (bool enableResponseEncoding : trueFalse) {
+
+ for (bool enableResponseEncoding : trueFalse) {
r.EnableResponseEncoding = enableResponseEncoding;
-
+
const TString reqTypes[] = {"GET", "POST"};
for (const TString& reqType : reqTypes) {
r.Type = reqType;
-
+
const TString encoders[] = {"", "deflate"};
for (const TString& encoder : encoders) {
r.ContentEncoding = encoder;
-
- for (bool expect100Continue : trueFalse) {
+
+ for (bool expect100Continue : trueFalse) {
r.Expect100Continue = expect100Continue;
TString resp = r.Execute();
UNIT_ASSERT_C(resp == res, "diff echo response for request:\n" + r.GetDescription());
@@ -365,12 +365,12 @@ Y_UNIT_TEST_SUITE(THttpServerTest) {
}
server.Stop();
- }
- }
+ }
+ }
Y_UNIT_TEST(TestReusePortEnabled) {
if (!IsReusePortAvailable()) {
- return; // skip test
+ return; // skip test
}
TString res = TestData();
TPortManager pm;
@@ -383,7 +383,7 @@ Y_UNIT_TEST_SUITE(THttpServerTest) {
}
for (ui32 testRun = 0; testRun < 3; testRun++) {
- for (auto& server : servers) {
+ for (auto& server : servers) {
// start servers one at a time and check at least one of them is replying
UNIT_ASSERT(server->Start());
@@ -391,7 +391,7 @@ Y_UNIT_TEST_SUITE(THttpServerTest) {
UNIT_ASSERT_C(r.Execute() == res, "diff echo response for request:\n" + r.GetDescription());
}
- for (auto& server : servers) {
+ for (auto& server : servers) {
// ping servers and stop them one at a time
// at the last iteration only one server is still working and then gets stopped as well
@@ -471,7 +471,7 @@ Y_UNIT_TEST_SUITE(THttpServerTest) {
return true;
}
};
-
+
public:
TClientRequest* CreateClient() override {
return new TRequest();
@@ -684,7 +684,7 @@ Y_UNIT_TEST_SUITE(THttpServerTest) {
server.Stop();
};
-#if 0
+#if 0
Y_UNIT_TEST(TestSocketsLeak) {
const bool trueFalse[] = {true, false};
TPortManager portManager;
@@ -709,7 +709,7 @@ Y_UNIT_TEST_SUITE(THttpServerTest) {
server.BusyThread();
for (size_t i = 0; i < 3; ++i) {
- auto func = [&server, port, keepAlive]() {
+ auto func = [&server, port, keepAlive]() {
server.BusyThread();
THolder<TTestRequest> r = MakeHolder<TTestRequest>(port);
r->KeepAliveConnection = keepAlive;
@@ -722,7 +722,7 @@ Y_UNIT_TEST_SUITE(THttpServerTest) {
Sleep(TDuration::MilliSeconds(100));
server.BusyThread(); // we wait while connections are established by the
// system and accepted by the server
- server.Free(3); // we release all connections processing
+ server.Free(3); // we release all connections processing
for (auto&& thread : threads) {
thread->Join();
@@ -735,5 +735,5 @@ Y_UNIT_TEST_SUITE(THttpServerTest) {
UNIT_ASSERT_EQUAL_C(server.RepliesCount(), 1, "only one request should have been processed, got " + ToString(server.RepliesCount()));
}
}
-#endif
-}
+#endif
+}
diff --git a/library/cpp/http/server/options.cpp b/library/cpp/http/server/options.cpp
index 391ac68a11..05c954384a 100644
--- a/library/cpp/http/server/options.cpp
+++ b/library/cpp/http/server/options.cpp
@@ -1,12 +1,12 @@
-#include "options.h"
-
+#include "options.h"
+
#include <util/string/cast.h>
-#include <util/digest/numeric.h>
-#include <util/network/ip.h>
-#include <util/network/socket.h>
-#include <util/generic/hash_set.h>
-#include <util/generic/yexception.h>
-
+#include <util/digest/numeric.h>
+#include <util/network/ip.h>
+#include <util/network/socket.h>
+#include <util/generic/hash_set.h>
+#include <util/generic/yexception.h>
+
using TAddr = THttpServerOptions::TAddr;
static inline TString AddrToString(const TAddr& addr) {
@@ -16,28 +16,28 @@ static inline TString AddrToString(const TAddr& addr) {
static inline TNetworkAddress ToNetworkAddr(const TString& address, ui16 port) {
if (address.empty() || address == TStringBuf("*")) {
return TNetworkAddress(port);
- }
-
+ }
+
return TNetworkAddress(address, port);
-}
-
-void THttpServerOptions::BindAddresses(TBindAddresses& ret) const {
+}
+
+void THttpServerOptions::BindAddresses(TBindAddresses& ret) const {
THashSet<TString> check;
-
+
for (auto addr : BindSockaddr) {
if (!addr.Port) {
addr.Port = Port;
- }
-
+ }
+
const TString straddr = AddrToString(addr);
if (check.find(straddr) == check.end()) {
check.insert(straddr);
ret.push_back(ToNetworkAddr(addr.Addr, addr.Port));
- }
- }
-
- if (ret.empty()) {
+ }
+ }
+
+ if (ret.empty()) {
ret.push_back(Host ? TNetworkAddress(Host, Port) : TNetworkAddress(Port));
- }
-}
+ }
+}
diff --git a/library/cpp/http/server/options.h b/library/cpp/http/server/options.h
index 28ce8be0e1..38eda0e5e7 100644
--- a/library/cpp/http/server/options.h
+++ b/library/cpp/http/server/options.h
@@ -1,49 +1,49 @@
#pragma once
-
-#include <util/network/ip.h>
-#include <util/network/init.h>
+
+#include <util/network/ip.h>
+#include <util/network/init.h>
#include <util/network/address.h>
#include <util/generic/size_literals.h>
#include <util/generic/string.h>
-#include <util/generic/vector.h>
+#include <util/generic/vector.h>
#include <util/datetime/base.h>
-
-class THttpServerOptions {
-public:
+
+class THttpServerOptions {
+public:
inline THttpServerOptions(ui16 port = 17000) noexcept
: Port(port)
- {
- }
-
+ {
+ }
+
using TBindAddresses = TVector<TNetworkAddress>;
- void BindAddresses(TBindAddresses& ret) const;
-
+ void BindAddresses(TBindAddresses& ret) const;
+
inline THttpServerOptions& AddBindAddress(const TString& address, ui16 port) {
const TAddr addr = {
- address,
- port,
- };
-
+ address,
+ port,
+ };
+
BindSockaddr.push_back(addr);
return *this;
}
inline THttpServerOptions& AddBindAddress(const TString& address) {
return AddBindAddress(address, 0);
- }
-
+ }
+
inline THttpServerOptions& EnableKeepAlive(bool enable) noexcept {
- KeepAliveEnabled = enable;
-
- return *this;
- }
-
+ KeepAliveEnabled = enable;
+
+ return *this;
+ }
+
inline THttpServerOptions& EnableCompression(bool enable) noexcept {
- CompressionEnabled = enable;
-
- return *this;
- }
-
+ CompressionEnabled = enable;
+
+ return *this;
+ }
+
inline THttpServerOptions& EnableRejectExcessConnections(bool enable) noexcept {
RejectExcessConnections = enable;
@@ -63,11 +63,11 @@ public:
}
inline THttpServerOptions& SetThreads(ui32 threads) noexcept {
- nThreads = threads;
-
- return *this;
- }
-
+ nThreads = threads;
+
+ return *this;
+ }
+
/// Default interface name to bind the server. Used when none of BindAddress are provided.
inline THttpServerOptions& SetHost(const TString& host) noexcept {
Host = host;
@@ -77,35 +77,35 @@ public:
/// Default port to bind the server. Used when none of BindAddress are provided.
inline THttpServerOptions& SetPort(ui16 port) noexcept {
- Port = port;
-
- return *this;
- }
-
+ Port = port;
+
+ return *this;
+ }
+
inline THttpServerOptions& SetMaxConnections(ui32 mc = 0) noexcept {
- MaxConnections = mc;
-
- return *this;
- }
-
+ MaxConnections = mc;
+
+ return *this;
+ }
+
inline THttpServerOptions& SetMaxQueueSize(ui32 mqs = 0) noexcept {
- MaxQueueSize = mqs;
-
- return *this;
- }
+ MaxQueueSize = mqs;
+
+ return *this;
+ }
inline THttpServerOptions& SetClientTimeout(const TDuration& timeout) noexcept {
- ClientTimeout = timeout;
+ ClientTimeout = timeout;
+
+ return *this;
+ }
- return *this;
- }
-
inline THttpServerOptions& SetListenBacklog(int val) noexcept {
- ListenBacklog = val;
-
- return *this;
- }
-
+ ListenBacklog = val;
+
+ return *this;
+ }
+
inline THttpServerOptions& SetOutputBufferSize(size_t val) noexcept {
OutputBufferSize = val;
@@ -149,19 +149,19 @@ public:
bool KeepAliveEnabled = true;
bool CompressionEnabled = false;
bool RejectExcessConnections = false;
- bool ReusePort = false; // set SO_REUSEPORT socket option
+ bool ReusePort = false; // set SO_REUSEPORT socket option
bool ReuseAddress = true; // set SO_REUSEADDR socket option
- TAddrs BindSockaddr;
- ui16 Port = 17000; // The port on which to run the web server
- TString Host; // DNS entry
- const char* ServerName = "YWS/1.0"; // The Web server name to return in HTTP headers
- ui32 nThreads = 0; // Thread count for requests processing
- ui32 MaxQueueSize = 0; // Max allowed request count in queue
+ TAddrs BindSockaddr;
+ ui16 Port = 17000; // The port on which to run the web server
+ TString Host; // DNS entry
+ const char* ServerName = "YWS/1.0"; // The Web server name to return in HTTP headers
+ ui32 nThreads = 0; // Thread count for requests processing
+ ui32 MaxQueueSize = 0; // Max allowed request count in queue
ui32 nFThreads = 1;
ui32 MaxFQueueSize = 0;
ui32 MaxConnections = 100;
int ListenBacklog = SOMAXCONN;
- TDuration ClientTimeout;
+ TDuration ClientTimeout;
size_t OutputBufferSize = 0;
ui64 MaxInputContentLength = sizeof(size_t) <= 4 ? 2_GB : 64_GB;
size_t MaxRequestsPerConnection = 0; // If keep-alive is enabled, request limit before connection is closed
@@ -173,4 +173,4 @@ public:
TString ListenThreadName = "HttpListen";
TString RequestsThreadName = "HttpServer";
TString FailRequestsThreadName = "HttpServer";
-};
+};
diff --git a/library/cpp/http/server/response.cpp b/library/cpp/http/server/response.cpp
index 3c7a3e6a93..52d64c91ce 100644
--- a/library/cpp/http/server/response.cpp
+++ b/library/cpp/http/server/response.cpp
@@ -1,7 +1,7 @@
#include "response.h"
-
+
#include <util/stream/output.h>
-#include <util/stream/mem.h>
+#include <util/stream/mem.h>
#include <util/string/cast.h>
THttpResponse& THttpResponse::AddMultipleHeaders(const THttpHeaders& headers) {
@@ -11,16 +11,16 @@ THttpResponse& THttpResponse::AddMultipleHeaders(const THttpHeaders& headers) {
return *this;
}
-THttpResponse& THttpResponse::SetContentType(const TStringBuf& contentType) {
+THttpResponse& THttpResponse::SetContentType(const TStringBuf& contentType) {
Headers.AddOrReplaceHeader(THttpInputHeader("Content-Type", ToString(contentType)));
-
- return *this;
+
+ return *this;
}
void THttpResponse::OutTo(IOutputStream& os) const {
TVector<IOutputStream::TPart> parts;
const size_t FIRST_LINE_PARTS = 3;
- const size_t HEADERS_PARTS = Headers.Count() * 4;
+ const size_t HEADERS_PARTS = Headers.Count() * 4;
const size_t CONTENT_PARTS = 5;
parts.reserve(FIRST_LINE_PARTS + HEADERS_PARTS + CONTENT_PARTS);
@@ -30,20 +30,20 @@ void THttpResponse::OutTo(IOutputStream& os) const {
parts.push_back(IOutputStream::TPart::CrLf());
// headers
- for (THttpHeaders::TConstIterator i = Headers.Begin(); i != Headers.End(); ++i) {
+ for (THttpHeaders::TConstIterator i = Headers.Begin(); i != Headers.End(); ++i) {
parts.push_back(IOutputStream::TPart(i->Name()));
parts.push_back(IOutputStream::TPart(TStringBuf(": ")));
parts.push_back(IOutputStream::TPart(i->Value()));
parts.push_back(IOutputStream::TPart::CrLf());
}
- char buf[50];
-
+ char buf[50];
+
if (!Content.empty()) {
- TMemoryOutput mo(buf, sizeof(buf));
+ TMemoryOutput mo(buf, sizeof(buf));
mo << Content.size();
-
+
parts.push_back(IOutputStream::TPart(TStringBuf("Content-Length: ")));
parts.push_back(IOutputStream::TPart(buf, mo.Buf() - buf));
parts.push_back(IOutputStream::TPart::CrLf());
@@ -51,15 +51,15 @@ void THttpResponse::OutTo(IOutputStream& os) const {
// content
parts.push_back(IOutputStream::TPart::CrLf());
-
+
if (!Content.empty()) {
parts.push_back(IOutputStream::TPart(Content));
}
os.Write(parts.data(), parts.size());
-}
-
-template <>
+}
+
+template <>
void Out<THttpResponse>(IOutputStream& os, const THttpResponse& resp) {
- resp.OutTo(os);
+ resp.OutTo(os);
}
diff --git a/library/cpp/http/server/response.h b/library/cpp/http/server/response.h
index 7880babac5..a75cb85605 100644
--- a/library/cpp/http/server/response.h
+++ b/library/cpp/http/server/response.h
@@ -1,8 +1,8 @@
#pragma once
-
+
#include <library/cpp/http/misc/httpcodes.h>
#include <library/cpp/http/io/stream.h>
-
+
#include <util/generic/strbuf.h>
#include <util/string/cast.h>
@@ -12,23 +12,23 @@ class IOutputStream;
class THttpResponse {
public:
THttpResponse() noexcept
- : Code(HTTP_OK)
- {
- }
-
+ : Code(HTTP_OK)
+ {
+ }
+
explicit THttpResponse(HttpCodes code) noexcept
: Code(code)
{
}
- template <typename ValueType>
+ template <typename ValueType>
THttpResponse& AddHeader(const TString& name, const ValueType& value) {
return AddHeader(THttpInputHeader(name, ToString(value)));
}
THttpResponse& AddHeader(const THttpInputHeader& header) {
Headers.AddHeader(header);
-
+
return *this;
}
@@ -38,8 +38,8 @@ public:
return Headers;
}
- THttpResponse& SetContentType(const TStringBuf& contentType);
-
+ THttpResponse& SetContentType(const TStringBuf& contentType);
+
/**
* @note If @arg content isn't empty its size is automatically added as a
* "Content-Length" header during output to IOutputStream.
@@ -47,7 +47,7 @@ public:
*/
THttpResponse& SetContent(const TString& content) {
Content = content;
-
+
return *this;
}
@@ -61,8 +61,8 @@ public:
* @see IOutputStream& operator << (IOutputStream&, const THttpResponse&)
*/
THttpResponse& SetContent(const TString& content, const TStringBuf& contentType) {
- return SetContent(content).SetContentType(contentType);
- }
+ return SetContent(content).SetContentType(contentType);
+ }
HttpCodes HttpCode() const {
return Code;
diff --git a/library/cpp/http/server/response_ut.cpp b/library/cpp/http/server/response_ut.cpp
index ecd41015d9..73e2112ad3 100644
--- a/library/cpp/http/server/response_ut.cpp
+++ b/library/cpp/http/server/response_ut.cpp
@@ -2,11 +2,11 @@
#include <library/cpp/testing/unittest/registar.h>
-#include <util/string/cast.h>
-
+#include <util/string/cast.h>
+
Y_UNIT_TEST_SUITE(TestHttpResponse) {
Y_UNIT_TEST(TestCodeOnly) {
- UNIT_ASSERT_STRINGS_EQUAL(ToString(THttpResponse()), "HTTP/1.1 200 Ok\r\n\r\n");
+ UNIT_ASSERT_STRINGS_EQUAL(ToString(THttpResponse()), "HTTP/1.1 200 Ok\r\n\r\n");
UNIT_ASSERT_STRINGS_EQUAL(ToString(THttpResponse(HTTP_NOT_FOUND)), "HTTP/1.1 404 Not found\r\n\r\n");
}
@@ -70,7 +70,7 @@ Y_UNIT_TEST_SUITE(TestHttpResponse) {
"Content-Length: 10\r\n"
"\r\n"
"0123456789";
- UNIT_ASSERT_STRINGS_EQUAL(ToString(THttpResponse().SetContent("0123456789")),
+ UNIT_ASSERT_STRINGS_EQUAL(ToString(THttpResponse().SetContent("0123456789")),
EXPECTED);
}
@@ -80,8 +80,8 @@ Y_UNIT_TEST_SUITE(TestHttpResponse) {
"Content-Length: 28\r\n"
"\r\n"
"<xml><tag value=\"1\" /></xml>";
- THttpResponse resp;
- resp.SetContent("<xml><tag value=\"1\" /></xml>").SetContentType("text/xml");
+ THttpResponse resp;
+ resp.SetContent("<xml><tag value=\"1\" /></xml>").SetContentType("text/xml");
UNIT_ASSERT_STRINGS_EQUAL(ToString(resp), EXPECTED);
}
@@ -90,8 +90,8 @@ Y_UNIT_TEST_SUITE(TestHttpResponse) {
resp.AddHeader(THttpInputHeader("X-Header-1", "ValueOne"))
.AddHeader("X-Header-2", "ValueTwo")
.AddHeader(THttpInputHeader("X-Header-3", "ValueThree"))
- .SetContent("Some stuff")
- .SetContentType("text/plain");
+ .SetContent("Some stuff")
+ .SetContentType("text/plain");
THttpResponse copy = resp;
UNIT_ASSERT_STRINGS_EQUAL(ToString(copy), ToString(resp));
@@ -102,19 +102,19 @@ Y_UNIT_TEST_SUITE(TestHttpResponse) {
resp.AddHeader(THttpInputHeader("X-Header-1", "ValueOne"));
resp.AddHeader(THttpInputHeader("X-Header-2", "ValueTwo"));
resp.AddHeader(THttpInputHeader("X-Header-3", "ValueThree"));
- resp.SetContent("Some stuff").SetContentType("text/plain");
+ resp.SetContent("Some stuff").SetContentType("text/plain");
- THttpResponse copy;
+ THttpResponse copy;
copy = resp;
UNIT_ASSERT_STRINGS_EQUAL(ToString(copy), ToString(resp));
}
Y_UNIT_TEST(TestEmptyContent) {
- UNIT_ASSERT_STRINGS_EQUAL(ToString(THttpResponse().SetContent("")), "HTTP/1.1 200 Ok\r\n\r\n");
+ UNIT_ASSERT_STRINGS_EQUAL(ToString(THttpResponse().SetContent("")), "HTTP/1.1 200 Ok\r\n\r\n");
}
Y_UNIT_TEST(TestReturnReference) {
- THttpResponse resp;
+ THttpResponse resp;
UNIT_ASSERT_EQUAL(&resp, &resp.AddHeader("Header1", 1));
UNIT_ASSERT_EQUAL(&resp, &resp.AddHeader(THttpInputHeader("Header2", "2")));
@@ -124,7 +124,7 @@ Y_UNIT_TEST_SUITE(TestHttpResponse) {
UNIT_ASSERT_EQUAL(&resp, &resp.AddMultipleHeaders(headers));
UNIT_ASSERT_EQUAL(&resp, &resp.SetContent("some stuff"));
- UNIT_ASSERT_EQUAL(&resp, &resp.SetContent("some other stuff").SetContentType("text/plain"));
+ UNIT_ASSERT_EQUAL(&resp, &resp.SetContent("some other stuff").SetContentType("text/plain"));
}
Y_UNIT_TEST(TestSetContentType) {
diff --git a/library/cpp/http/server/ut/ya.make b/library/cpp/http/server/ut/ya.make
index 17c20a8138..bcb4d4c0b8 100644
--- a/library/cpp/http/server/ut/ya.make
+++ b/library/cpp/http/server/ut/ya.make
@@ -2,8 +2,8 @@ UNITTEST_FOR(library/cpp/http/server)
OWNER(pg)
-SIZE(MEDIUM)
-
+SIZE(MEDIUM)
+
SRCS(
http_ut.cpp
response_ut.cpp
diff --git a/library/cpp/http/server/ya.make b/library/cpp/http/server/ya.make
index 7b6bd59024..bae6f33306 100644
--- a/library/cpp/http/server/ya.make
+++ b/library/cpp/http/server/ya.make
@@ -1,27 +1,27 @@
-LIBRARY()
-
-OWNER(
- pg
+LIBRARY()
+
+OWNER(
+ pg
mvel
kulikov
g:base
g:middle
-)
-
-SRCS(
- conn.cpp
- http.cpp
- http_ex.cpp
- options.cpp
+)
+
+SRCS(
+ conn.cpp
+ http.cpp
+ http_ex.cpp
+ options.cpp
response.cpp
-)
-
+)
+
PEERDIR(
library/cpp/http/misc
library/cpp/http/io
library/cpp/threading/equeue
)
-END()
+END()
RECURSE_FOR_TESTS(ut)