53
59
/* Create new CONNECTOR structure to hit the specified URL using HTTP
54
* with either POST or GET method.
60
* with either POST / GET or CONNECT method.
55
61
* Use the configuration values recorded in "net_info". If "net_info" is NULL,
56
62
* then use the default info (created by "ConnNetInfo_Create(0)").
64
* If "net_info" does not explicitly specify an HTTP request method (i.e.
65
* it has it as "eReqMethod_Any"), then the actual method sent to the HTTP
66
* server depends on whether any data have been written to the connection
67
* with CONN_Write(): the presense of pending data will cause POST request
68
* (with Content-Length tag provided automatically and reflecting the total
69
* pending data size), and GET request method will result in the absence
70
* of any data. An explicit value for the request method will cause the
71
* specified request to be used regardless of pending data, and flagging
72
* an error if any data will have to be sent with GET (per the RFC).
58
74
* In order to workaround some HTTP communication features, this code does:
59
75
* 1) Accumulate all output data in an internal memory buffer until the
60
76
* first "Read" (or "Peek", or "Close", or "Wait" on read) is attempted
61
* (also see fHCC_Flushable flag below).
62
* 2) On the first "Read" (or "Peek", or "Close", or "Wait" on read), compose
63
* and send the whole HTTP request as:
64
* {POST|GET} <info->path>?<info->args> HTTP/1.0\r\n
77
* (also see fHTTP_Flushable flag below).
78
* 2) On the first "Read" (or "Peek", or "Close", or "Wait" on read),
79
* compose and send the whole HTTP request as:
80
* {POST|GET} <net_info->path>?<net_info->args> HTTP/1.0\r\n
65
81
* <user_header\r\n>
66
82
* Content-Length: <accumulated_data_length>\r\n
68
84
* <accumulated_data>
70
* if <user->header> is neither a NULL pointer nor an empty string, then:
71
* - it must NOT contain "empty lines": '\r\n\r\n';
72
* - it must be terminated by a single '\r\n';
86
* if <user_header> is neither a NULL pointer nor an empty string, then:
87
* - it must NOT contain any "empty lines": "\r\n\r\n";
88
* - it must be terminated by a single "\r\n";
73
89
* - it gets inserted to the HTTP header "as is", without any
74
* automatic checking or encoding.
90
* automatic checking or encoding;
91
* - the "user_header" specified in the arguments overrides any user
92
* header that can be provided via the "net_info" argument, see
93
* ConnNetInfo_OverrideUserHeader() from <connect/ncbi_connutil.h>.
76
95
* Data may depart to server side earlier if Flush()'ed in
77
* fHCC_Flushable connector, see below in "flags".
78
* After the request has been sent, reply data from the peer
79
* CGI program are then can be actually read out.
80
* 4) On any "Write" operation. which follows data reading, the connection
81
* to the peer CGI program is forcedly closed (the peer CGI process will
82
* presumably die if has not done yet so), and data to be written are
83
* again are stored in the buffer until next "Read" etc, see item 1).
85
* *) If "fHCC_AutoReconnect" is set in "flags", then the connector makes
86
* an automatic reconnect to the same CGI program with just the
87
* same parameters, and micro-session steps (1,2,3) are repeated with
88
* another instance of the CGI program.
90
* If "fHCC_AutoReconnect" is not set then only one
96
* fHTTP_Flushable connector, see below in "flags".
97
* 3) After the request has been sent, then the response data from
98
* the peer (usually a CGI program) can be actually read out.
99
* 4) On any "Write" operation, which follows data reading, the connection
100
* to the peer is forcedly closed (the peer CGI process will presumably
101
* die if it has not done so yet on its own), and data to be written
102
* again get stored in the buffer until next "Read" etc, see item 1).
104
* *) If "fHTTP_AutoReconnect" is set in "flags", then the connector makes
105
* an automatic reconnect to the same URL with just the same parameters
106
* for each micro-session steps (1,2,3) repeated.
108
* If "fHTTP_AutoReconnect" is not set then only a single
91
109
* "Write ... Write Read ... Read" micro-session is allowed, any
92
* following "Write" attempt fails with error status "eIO_Closed".
110
* following "Write" attempt fails with an error "eIO_Closed".
97
115
* make the connector to send at least the HTTP header on "CLOSE" and
98
116
* re-"CONNECT", even if no data was written
117
* fHTTP_KeepHeader --
100
118
* do not strip HTTP header (i.e. everything up to the first "\r\n\r\n",
101
* including the "\r\n\r\n") from the CGI script's response
102
* fHCC_UrlDecodeInput --
103
* strip the HTTP header from the input data; assume the input
104
* data are single-part, URL-encoded; perform the URL-decoding on read
105
* NOTE: this flag disables the "fHCC_KeepHeader" flag
119
* including the "\r\n\r\n") from the CGI script's response (including
120
* any server error, which then is made available for reading as well)
121
* NOTE this flag disables automatic authorization, redirection, etc.
122
* fHTTP_UrlDecodeInput --
123
* assume the response body single-part, URL-encoded; perform the
124
* URL-decoding on read, and deliver decoded data to the user
125
* fHTTP_DropUnread --
107
126
* do not collect incoming data in "Read" mode before switching into
108
* "Write" mode for storing output data in buffer; by default all
127
* "Write" mode for storing output data in buffer; by default all
109
128
* data sent by the CGI program are stored even if not all requested
110
129
* before "Write" following "Read" was issued (stream emulation)
112
* do not do internal reading into temporary buffer while sending
113
* data to CGI program; by default any send operation tries to
131
* do *not* do internal reading into temporary buffer while sending
132
* data to HTTP server; by default any send operation tries to
114
133
* extract data(if any) coming back from the CGI program in order to
115
* prevent connection blocking
117
* usually all data written to the connection are kept until
134
* prevent connection blocking (due to data clogging)
136
* by default all data written to the connection are kept until
118
137
* read begins (even though Flush() might have been called in between
119
* the writes). With this flag set, Flush() will result the data
138
* the writes); with this flag set, Flush() will result the data
120
139
* to be actually sent to server side, so the following write will form
121
* new request, and not get added to the previous one.
122
* fHCC_InsecureRedirect --
140
* new request, and not get added to the previous one
141
* fHTTP_InsecureRedirect --
123
142
* for security reasons the following redirects comprise security risk
124
143
* and, thus, are prohibited: switching from https to http, and
125
* re-posting data (regardless of the transport, either http or https).
126
* This flag allows such redirects (if needed) to be honored.
127
* fHCC_NoAutoRetry --
144
* re-posting data (regardless of the transport, either http or https);
145
* this flag allows such redirects (if needed) to be honored
146
* fHTTP_NoAutoRetry --
128
147
* do not attempt any auto-retries in case of failing connections
129
* (this flag effectively means having SConnNetInfo::max_try set to 1).
131
* NOTE: the URL encoding/decoding (in the "fHCC_Url_*" cases and "info->args")
132
* is performed by URL_Encode() and URL_Decode() -- "ncbi_connutil.[ch]".
148
* (this flag effectively means having SConnNetInfo::max_try set to 1)
150
* NOTE: the URL encoding/decoding (in the "fHTTP_Url_*" cases and
151
* "net_info->args") is performed by URL_Encode() and URL_Decode()
152
* -- see "ncbi_connutil.[ch]".
155
* SConnNetInfo, ConnNetInfo_OverrideUserHeader, URL_Encode, URL_Decode
136
fHCC_AutoReconnect = 0x1, /* see (*) above */
137
fHCC_SureFlush = 0x2, /* always send HTTP request on CLOSE/RECONN*/
138
fHCC_KeepHeader = 0x4, /* dont strip HTTP header from CGI response*/
139
fHCC_UrlDecodeInput = 0x8, /* strip HTTP header, URL-decode content */
140
fHCC_UrlEncodeOutput = 0x10, /* URL-encode all output data */
141
fHCC_UrlCodec = 0x18, /* fHCC_UrlDecodeInput | ...EncodeOutput */
142
fHCC_UrlEncodeArgs = 0x20, /* URL-encode "info->args" */
143
fHCC_DropUnread = 0x40, /* each microsession drops yet unread data */
144
fHCC_NoUpread = 0x80, /* do not use SOCK_SetReadOnWrite() at all */
145
fHCC_Flushable = 0x100,/* connector will really flush on Flush() */
146
fHCC_InsecureRedirect = 0x200,/* any redirect will be honored */
147
fHCC_NoAutoRetry = 0x400 /* no auto-retries allowed */
159
fHTTP_AutoReconnect = 0x1, /* see (*) above */
160
fHTTP_SureFlush = 0x2, /* always send HTTP request on CLOSE/RECONN*/
161
fHTTP_KeepHeader = 0x4, /* dont strip HTTP header from CGI response*/
162
fHTTP_UrlDecodeInput = 0x8, /* URL-decode content of the response body */
163
fHTTP_UrlEncodeOutput = 0x10, /* URL-encode all output data */
164
fHTTP_UrlCodec = 0x18, /* fHTTP_UrlDecodeInput | ...EncodeOutput */
165
fHTTP_UrlEncodeArgs = 0x20, /* URL-encode "info->args" */
166
fHTTP_DropUnread = 0x40, /* each microsession drops yet unread data */
167
fHTTP_NoUpread = 0x80, /* do not use SOCK_SetReadOnWrite() at all */
168
fHTTP_Flushable = 0x100,/* connector will really flush on Flush() */
169
fHTTP_InsecureRedirect= 0x200,/* any redirect will be honored */
170
fHTTP_NoAutoRetry = 0x400,/* no auto-retries allowed */
171
fHTTP_DetachableTunnel= 0x800 /* SOCK_Close() won't close the OS handle */
173
NCBI_HTTP_CONNECTOR_DEPRECATED
175
/* DEPRECATED, do not use! */
176
fHCC_AutoReconnect = fHTTP_AutoReconnect,
177
fHCC_SureFlush = fHTTP_SureFlush,
178
fHCC_KeepHeader = fHTTP_KeepHeader,
179
fHCC_UrlDecodeInput = fHTTP_UrlDecodeInput,
180
fHCC_UrlEncodeOutput = fHTTP_UrlEncodeOutput,
181
fHCC_UrlCodec = fHTTP_UrlCodec,
182
fHCC_UrlEncodeArgs = fHTTP_UrlEncodeArgs,
183
fHCC_DropUnread = fHTTP_DropUnread,
184
fHCC_NoUpread = fHTTP_NoUpread,
185
fHCC_Flushable = fHTTP_Flushable,
186
fHCC_InsecureRedirect = fHTTP_InsecureRedirect,
187
fHCC_NoAutoRetry = fHTTP_NoAutoRetry,
188
fHCC_DetachableTunnel = fHTTP_DetachableTunnel
149
typedef unsigned int THCC_Flags; /* bitwise OR of "EHCC_Flags" */
190
NCBI_HTTP_CONNECTOR_DEPRECATED
191
typedef unsigned int THCC_Flags; /* bitwise OR of "EHCC_Flags", deprecated */
192
typedef unsigned int THTTP_Flags; /* bitwise OR of "EHTTP_Flags" */
151
194
extern NCBI_XCONNECT_EXPORT CONNECTOR HTTP_CreateConnector
152
195
(const SConnNetInfo* net_info,
153
196
const char* user_header,
158
/* An extended version of HTTP_CreateConnector() to change the URL of the
159
* server CGI "on-the-fly":
160
* -- "parse_http_hdr()" is called each time the HTTP header received
161
* from HTTP server and only if fHCC_KeepHeader is NOT set; false return
162
* value is equivalent of having an error from the HTTP server itself.
163
* -- "adjust_net_info()" is invoked each time before starting a
164
* new "HTTP micro-session" making a hit if the prior hit has failed;
165
* it is passed "net_info" stored in the connector, and the number of
166
* previously unsuccessful attempts since the connection was opened;
167
* false return value terminates retry attempts.
168
* -- "adjust_cleanup()" is called when the connector is being destroyed.
201
/* An extended version of HTTP_CreateConnector() is able to change
202
* the URL of the server "on-the-fly":
203
* - "FHTTP_ParseHeader()" is called every time a new HTTP response header
204
* is received from the server, and only if fHTTP_KeepHeader is NOT set;
205
* a zero (false) return value is equivalent of having an error from
206
* the HTTP server itself;
207
* - "FHTTP_Adjust()" is invoked every time before starting a new
208
* "HTTP micro-session" making a hit when previous hit has failed;
209
* it is passed "net_info" stored in the connector, and the number of
210
* previously unsuccessful attempts since the connection was opened;
211
* a zero (false) return value ends retry attempts;
212
* - "FHTTP_Cleanup()" is called when the connector is about to be destroyed.
171
typedef int/*bool*/ (*FHttpParseHTTPHeader)
172
(const char* http_header, /* HTTP header to parse, '\0'-terminated */
173
void* adjust_data, /* supplemental user data */
174
int server_error /* != 0 if HTTP error */
177
typedef int/*bool*/ (*FHttpAdjustNetInfo)
178
(SConnNetInfo* net_info, /* net_info to adjust (in place) */
179
void* adjust_data, /* supplemental user data */
180
unsigned int failure_count /* how many failures since open */
183
typedef void (*FHttpAdjustCleanup)
184
(void* adjust_data /* supplemental user data for cleanup */
215
typedef int/*bool*/ (*FHTTP_ParseHeader)
216
(const char* http_header, /* HTTP header to parse, '\0'-terminated */
217
void* user_data, /* supplemental user data */
218
int server_error /* != 0 if HTTP error */
221
typedef int/*bool*/ (*FHTTP_Adjust)
222
(SConnNetInfo* net_info, /* net_info to adjust (in place) */
223
void* user_data, /* supplemental user data */
224
unsigned int failure_count /* how many failures since open */
227
typedef void (*FHTTP_Cleanup)
228
(void* user_data /* supplemental user data for cleanup */
187
231
extern NCBI_XCONNECT_EXPORT CONNECTOR HTTP_CreateConnectorEx
188
(const SConnNetInfo* net_info,
190
FHttpParseHTTPHeader parse_http_hdr, /* may be NULL, then no addtl. parsing */
191
FHttpAdjustNetInfo adjust_net_info,/* may be NULL, then no adjustments */
192
void* adjust_data, /* for "adjust_info" & "adjust_cleanup"*/
193
FHttpAdjustCleanup adjust_cleanup /* may be NULL */
232
(const SConnNetInfo* net_info,
234
FHTTP_ParseHeader parse_header, /* may be NULL, then no addtl. parsing */
235
void* user_data, /* user data for HTTP callbacks (CBs) */
236
FHTTP_Adjust adjust, /* may be NULL, then no adjustments */
237
FHTTP_Cleanup cleanup /* may be NULL, then no cleanup */
241
/* Create a tunnel to "net_info->host:net_info->port" via an HTTP proxy
242
* server located at "net_info->http_proxy_host:net_info->http_proxy_port".
243
* Return the tunnel as a socket via the last parameter. For compatibility
244
* with future API extensions, please make sure *sock == NULL when the call
247
* eIO_Success if the tunnel has been successfully created;
248
* otherwise, return an error code and set *sock to NULL upon return.
250
* ESOCK_Flags, SOCK_CreateEx, SOCK_Close
252
extern NCBI_XCONNECT_EXPORT EIO_Status HTTP_CreateTunnelEx
253
(const SConnNetInfo* net_info,
255
const void* init_data,
261
/* Same as HTTP_CreateTunnelEx(net_info, flags, 0, 0, sock) */
262
extern NCBI_XCONNECT_EXPORT EIO_Status HTTP_CreateTunnel
263
(const SConnNetInfo* net_info,
197
269
/* Set message hook procedure for messages originating from NCBI via HTTP.