-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Hi,
I have created axis2_http_client.h and axis2_http_client.c to implement the HTTP client functionality. Even though it can handle simple request/response scenarios, lot of improvemnts have to be done to handle complex cases (redirection, 100-continues). Pls review and commit the initial version. - - Sahan -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.1 (GNU/Linux) Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org iQEVAwUBQ8HP7anIlEsDdb85AQI2wAf/VTXUshNeH2N2u0HJV/kB3BuqRkzeOOe1 RqZ9M/2l6+nfSQ6cGJSxn1V3nirGxgxV2383q3v+wCPc8D+2dtcTsbpBUHa7pxb2 V9o4/89uaWtRjkf40Anzu7b0X2AVEXxvU3FA4GKteX8beONdAz1g3RXAaCp3UIB+ UlATA3NvoHZ+1RpUlS39J6jOPBsqXQopODdjmvbRfgLswzhkJsad1X2EALte5xoP J9SeW8OunQPf7gUEFREDmSExJ78Aq5sk7a+yOaPW9P8JQETHnrMEpbdazzzO7pTD I9utslYjAcQyIaf0ZY6ZOmj4IAUHiWJq0oFFnPNJ2iGP40GKJHQ3ng== =Kx3f -----END PGP SIGNATURE-----
/* * Copyright 2004,2005 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef AXIS2_HTTP_CLIENT_H #define AXIS2_HTTP_CLIENT_H /** * @file axis2_http_client.h * @brief axis2 HTTP Header name:value pair implementation */ #include <axis2.h> #include <axis2_defines.h> #include <axis2_env.h> #include <axis2_http_simple_response.h> #include <axis2_http_simple_request.h> #include <axis2_url.h> #ifdef __cplusplus extern "C" { #endif /** * @ingroup axis2_core_transport_http * @{ */ typedef struct axis2_http_client_ops axis2_http_client_ops_t; typedef struct axis2_http_client axis2_http_client_t; /** * @brief HTTP Client ops struct * Encapsulator struct for ops of axis2_http_client */ AXIS2_DECLARE_DATA struct axis2_http_client_ops { axis2_status_t (AXIS2_CALL *send) (axis2_http_client_t *client, axis2_env_t **env, axis2_http_simple_request_t *request); int (AXIS2_CALL *recieve_header) (axis2_http_client_t *client, axis2_env_t **env); axis2_http_simple_response_t* (AXIS2_CALL *get_response) (axis2_http_client_t *client, axis2_env_t **env); axis2_status_t (AXIS2_CALL *set_url) (axis2_http_client_t *client, axis2_env_t **env, axis2_url_t *url); axis2_url_t* (AXIS2_CALL *get_url) (axis2_http_client_t *client, axis2_env_t **env); axis2_status_t (AXIS2_CALL *set_timeout) (axis2_http_client_t *client, axis2_env_t **env, int timeout_ms); int (AXIS2_CALL *get_timeout) (axis2_http_client_t *client, axis2_env_t **env); axis2_status_t (AXIS2_CALL *free) (axis2_http_client_t *client, axis2_env_t **env); }; /** * @brief HTTP Client struct * Axis2 HTTP Client */ AXIS2_DECLARE_DATA struct axis2_http_client { axis2_http_client_ops_t *ops; }; AXIS2_DECLARE(axis2_http_client_t *) axis2_http_client_create (axis2_env_t **env, axis2_url_t *url); /************************** Start of function macros **************************/ #define AXIS2_HTTP_CLIENT_SEND(client, env, request) \ ((client)->ops->send(client, env, request)) #define AXIS2_HTTP_CLIENT_RECIEVE_HEADER(client, env) \ ((client)->ops->recieve_header(client, env)) #define AXIS2_HTTP_CLIENT_GET_RESPONSE(client, env) \ ((client)->ops->get_response(client, env)) #define AXIS2_HTTP_CLIENT_SET_URL(client, env, url) \ ((client)->ops->set_url(client, env, url)) #define AXIS2_HTTP_CLIENT_GET_URL(client, env) \ ((client)->ops->get_url(client, env)) #define AXIS2_HTTP_CLIENT_SET_TIMEOUT(client, env, url, timeout) \ ((client)->ops->set_url(client, env, url, \ timeout)) #define AXIS2_HTTP_CLIENT_GET_TIMEOUT(client, env) \ ((client)->ops->get_url(client, env)) #define AXIS2_HTTP_CLIENT_FREE(client, env) \ ((client)->ops->free(client, env)) /************************** End of function macros ****************************/ /** @} */ #ifdef __cplusplus } #endif #endif /* AXIS2_HTTP_CLIENT_H */
/* * Copyright 2004,2005 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <axis2_http_client.h> #include <axis2_http_transport.h> #include <axis2_stream.h> #include <axis2_string.h> #include <axis2_network_handler.h> #include <axis2_http_request_line.h> #include <axis2_http_header.h> #include <axis2_http_status_line.h> /** * @brief HTTP Client struct impl * Axis2 HTTP Client impl */ typedef struct axis2_http_client_impl axis2_http_client_impl_t; struct axis2_http_client_impl { axis2_http_client_t http_client; int sockfd; axis2_stream_t *data_stream; axis2_url_t *url; axis2_http_simple_response_t *response; axis2_bool_t request_sent; int timeout; }; #define AXIS2_INTF_TO_IMPL(http_client) \ ((axis2_http_client_impl_t *)(http_client)) /***************************** Function clients *******************************/ axis2_status_t AXIS2_CALL axis2_http_client_send (axis2_http_client_t *client, axis2_env_t **env, axis2_http_simple_request_t *request); int AXIS2_CALL axis2_http_client_recieve_header (axis2_http_client_t *client, axis2_env_t **env); axis2_http_simple_response_t* AXIS2_CALL axis2_http_client_get_response (axis2_http_client_t *client, axis2_env_t **env); axis2_status_t AXIS2_CALL axis2_http_client_set_url (axis2_http_client_t *client, axis2_env_t **env, axis2_url_t *url); axis2_url_t* AXIS2_CALL axis2_http_client_get_url (axis2_http_client_t *client, axis2_env_t **env); axis2_status_t AXIS2_CALL axis2_http_client_set_timeout (axis2_http_client_t *client, axis2_env_t **env, int timeout_ms); int AXIS2_CALL axis2_http_client_get_timeout (axis2_http_client_t *client, axis2_env_t **env); axis2_status_t AXIS2_CALL axis2_http_client_free (axis2_http_client_t *client, axis2_env_t **env); /***************************** End of function clients ************************/ AXIS2_DECLARE(axis2_http_client_t *) axis2_http_client_create (axis2_env_t **env, axis2_url_t *url) { AXIS2_ENV_CHECK(env, NULL); axis2_http_client_impl_t *http_client_impl = (axis2_http_client_impl_t *)AXIS2_MALLOC ((*env)->allocator, sizeof(axis2_http_client_impl_t)); if(NULL == http_client_impl) { AXIS2_ERROR_SET((*env)->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); return NULL; } http_client_impl->url = url; http_client_impl->data_stream = NULL; http_client_impl->sockfd = -1; http_client_impl->response = NULL; http_client_impl->request_sent = AXIS2_FALSE; http_client_impl->timeout = AXIS2_HTTP_DEFAULT_CONNECTION_TIMEOUT; http_client_impl->http_client.ops = AXIS2_MALLOC((*env)->allocator, sizeof(axis2_http_client_ops_t)); if(NULL == http_client_impl->http_client.ops) { axis2_http_client_free((axis2_http_client_t*) http_client_impl, env); AXIS2_ERROR_SET((*env)->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); return NULL; } http_client_impl->http_client.ops->send = axis2_http_client_send; http_client_impl->http_client.ops->recieve_header = axis2_http_client_recieve_header; http_client_impl->http_client.ops->get_response = axis2_http_client_get_response; http_client_impl->http_client.ops->set_url = axis2_http_client_set_url; http_client_impl->http_client.ops->get_url = axis2_http_client_get_url; http_client_impl->http_client.ops->set_timeout = axis2_http_client_set_timeout; http_client_impl->http_client.ops->get_timeout = axis2_http_client_get_timeout; http_client_impl->http_client.ops->free = axis2_http_client_free; return &(http_client_impl->http_client); } axis2_status_t AXIS2_CALL axis2_http_client_free (axis2_http_client_t *client, axis2_env_t **env) { AXIS2_FUNC_PARAM_CHECK(client, env, AXIS2_FAILURE); axis2_http_client_impl_t *http_client_impl = AXIS2_INTF_TO_IMPL(client); if(NULL != http_client_impl->url) { AXIS2_URL_FREE(http_client_impl->url, env); http_client_impl->url = NULL; } if(NULL != http_client_impl->data_stream) { AXIS2_STREAM_FREE(http_client_impl->data_stream, env); http_client_impl->data_stream = NULL; } if(NULL != http_client_impl->response) { AXIS2_HTTP_SIMPLE_RESPONSE_FREE(http_client_impl->response, env); http_client_impl->response = NULL; } if(-1 != http_client_impl->sockfd) { axis2_network_handler_close_socket(env, http_client_impl->sockfd); http_client_impl->sockfd = -1; } if(NULL != client->ops) AXIS2_FREE((*env)->allocator, client->ops); AXIS2_FREE((*env)->allocator, AXIS2_INTF_TO_IMPL(client)); return AXIS2_SUCCESS; } axis2_status_t AXIS2_CALL axis2_http_client_send (axis2_http_client_t *client, axis2_env_t **env, axis2_http_simple_request_t *request) { axis2_http_client_impl_t *client_impl = NULL; char *wire_format = NULL; axis2_array_list_t *headers = NULL; char *str_header = NULL; char *str_body = NULL; char *str_request_line = NULL; int body_size = 0; int written = 0; AXIS2_FUNC_PARAM_CHECK(client, env, AXIS2_FAILURE); client_impl = AXIS2_INTF_TO_IMPL(client); if(NULL != client_impl->url) { AXIS2_ERROR_SET((*env)->error, AXIS2_ERROR_NULL_URL, AXIS2_FAILURE); } client_impl->sockfd = axis2_network_handler_open_socket(env, AXIS2_URL_GET_SERVER(client_impl->url, env), AXIS2_URL_GET_PORT(client_impl->url, env)); if(client_impl->sockfd < 0) { AXIS2_ERROR_SET((*env)->error, AXIS2_ERROR_SOCKET_ERROR, AXIS2_FAILURE); return AXIS2_FAILURE; } /* ONLY FOR TESTING * client_impl->data_stream = axis2_stream_create_file(env, * stdout); */ if(client_impl->timeout > 0) { axis2_network_handler_set_sock_option(env, client_impl->sockfd, SO_RCVTIMEO, client_impl->timeout); axis2_network_handler_set_sock_option(env, client_impl->sockfd, SO_SNDTIMEO, client_impl->timeout); } client_impl->data_stream = axis2_stream_create_socket(env, client_impl->sockfd); if(NULL == client_impl->data_stream) { axis2_network_handler_close_socket(env, client_impl->sockfd); return AXIS2_FAILURE; } headers = AXIS2_HTTP_SIMPLE_REQUEST_GET_HEADERS(request, env); if(NULL != headers) { int header_count = AXIS2_ARRAY_LIST_SIZE(headers, env); int i = 0; char *str_header2 = NULL; for(i = 0; i < header_count; i++) { axis2_http_header_t *tmp_header = (axis2_http_header_t*) AXIS2_ARRAY_LIST_GET(headers, env, i); axis2_char_t *header_ext_form = AXIS2_HTTP_HEADER_TO_EXTERNAL_FORM( tmp_header, env); str_header2 = AXIS2_STRACAT(str_header, header_ext_form, env); AXIS2_FREE((*env)->allocator, str_header); str_header = NULL; AXIS2_FREE((*env)->allocator, header_ext_form); header_ext_form = NULL; str_header = str_header2; } } str_request_line = AXIS2_HTTP_REQUEST_LINE_TO_STRING( AXIS2_HTTP_SIMPLE_REQUEST_GET_REQUEST_LINE(request, env) , env); wire_format = AXIS2_STRACAT(str_request_line, str_header, env); AXIS2_FREE((*env)->allocator, str_header); str_header = NULL; AXIS2_FREE((*env)->allocator, str_request_line); str_request_line = NULL; written = AXIS2_STREAM_WRITE(client_impl->data_stream, env, wire_format, AXIS2_STRLEN(wire_format)); AXIS2_FREE((*env)->allocator, wire_format); wire_format = NULL; written = AXIS2_STREAM_WRITE(client_impl->data_stream, env, AXIS2_HTTP_CRLF, 2); body_size = AXIS2_HTTP_SIMPLE_REQUEST_GET_BODY_BYTES(request, env, &str_body); if(body_size > 0 && NULL != str_body) { written = AXIS2_STREAM_WRITE(client_impl->data_stream, env, str_body, body_size); } written = AXIS2_STREAM_WRITE(client_impl->data_stream, env, AXIS2_HTTP_CRLF, 2); client_impl->request_sent = AXIS2_TRUE; if(NULL != str_body) { AXIS2_FREE((*env)->allocator, str_body); str_body = NULL; } return AXIS2_SUCCESS; } int AXIS2_CALL axis2_http_client_recieve_header(axis2_http_client_t *client, axis2_env_t **env) { int status_code = -1; axis2_http_client_impl_t *client_impl = NULL; axis2_http_status_line_t *status_line = NULL; char str_status_line[512]; char tmp_buf[3]; char str_header[512]; int read = 0; axis2_bool_t end_of_line = AXIS2_FALSE; axis2_bool_t end_of_headers = AXIS2_FALSE; AXIS2_FUNC_PARAM_CHECK(client, env, AXIS2_CRTICAL_FAILURE); client_impl = AXIS2_INTF_TO_IMPL(client); if(-1 == client_impl->sockfd || NULL == client_impl->data_stream || AXIS2_FALSE == client_impl->request_sent) { AXIS2_ERROR_SET((*env)->error, AXIS2_ERROR_HTTP_REQUEST_NOT_SENT, AXIS2_FAILURE); return -1; } /* read the status line */ memset(str_status_line, 0, 512); while((read = AXIS2_STREAM_READ(client_impl->data_stream, env, tmp_buf, 1)) > 0) { tmp_buf[read] = '\0'; strcat(str_status_line, tmp_buf); if(0 != strstr(str_status_line, AXIS2_HTTP_CRLF)) { end_of_line = AXIS2_TRUE; } if(AXIS2_TRUE == end_of_line) { break; } } status_line = axis2_http_status_line_create(env, str_status_line); if(NULL == status_line) { AXIS2_ERROR_SET((*env)->error, AXIS2_ERROR_INVALID_HTTP_INVALID_HEADER_START_LINE, AXIS2_FAILURE); return -1; } client_impl->response = axis2_http_simple_response_create_default(env); AXIS2_HTTP_SIMPLE_RESPONSE_SET_STAUTUS_LINE(client_impl->response, env, AXIS2_HTTP_STATUS_LINE_GET_HTTP_VERSION(status_line, env), AXIS2_HTTP_STATUS_LINE_GET_STATUS_CODE( status_line, env), AXIS2_HTTP_STATUS_LINE_GET_REASON_PHRASE(status_line, env)); /* now read the headers */ memset(str_header, 0, 512); end_of_line = AXIS2_FALSE; while(AXIS2_FALSE == end_of_headers) { while((read = AXIS2_STREAM_READ(client_impl->data_stream, env, tmp_buf, 1)) > 0) { tmp_buf[read] = '\0'; strcat(str_header, tmp_buf); if(0 != strstr(str_header, AXIS2_HTTP_CRLF)) { end_of_line = AXIS2_TRUE; } if(AXIS2_TRUE == end_of_line) { break; } } if(AXIS2_TRUE == end_of_line) { if(0 == AXIS2_STRCMP(str_header, AXIS2_HTTP_CRLF)) { end_of_headers = AXIS2_TRUE; } else { axis2_http_header_t *tmp_header = axis2_http_header_create_by_str(env, str_header); memset(str_header, 0, 512); if(NULL != tmp_header) { AXIS2_HTTP_SIMPLE_RESPONSE_SET_HEADER(client_impl->response, env, tmp_header); } } } end_of_line = AXIS2_FALSE; } AXIS2_HTTP_SIMPLE_RESPONSE_SET_BODY_STREAM(client_impl->response, env, client_impl->data_stream); if(NULL != status_line) { status_code = AXIS2_HTTP_STATUS_LINE_GET_STATUS_CODE(status_line, env); AXIS2_HTTP_STATUS_LINE_FREE(status_line, env); status_line = NULL; } return status_code; } axis2_http_simple_response_t* AXIS2_CALL axis2_http_client_get_response (axis2_http_client_t *client, axis2_env_t **env) { AXIS2_FUNC_PARAM_CHECK(client, env, NULL); return AXIS2_INTF_TO_IMPL(client)->response; } axis2_status_t AXIS2_CALL axis2_http_client_set_url (axis2_http_client_t *client, axis2_env_t **env, axis2_url_t *url) { AXIS2_FUNC_PARAM_CHECK(client, env, AXIS2_FAILURE); AXIS2_PARAM_CHECK((*env)->error, url, AXIS2_FAILURE); if(NULL != AXIS2_INTF_TO_IMPL(client)->url) { AXIS2_URL_FREE(AXIS2_INTF_TO_IMPL(client)->url, env); AXIS2_INTF_TO_IMPL(client)->url = NULL; } AXIS2_INTF_TO_IMPL(client)->url = url; return AXIS2_SUCCESS; } axis2_url_t* AXIS2_CALL axis2_http_client_get_url (axis2_http_client_t *client, axis2_env_t **env) { AXIS2_FUNC_PARAM_CHECK(client, env, NULL); return AXIS2_INTF_TO_IMPL(client)->url; } axis2_status_t AXIS2_CALL axis2_http_client_set_timeout (axis2_http_client_t *client, axis2_env_t **env, int timeout_ms) { AXIS2_FUNC_PARAM_CHECK(client, env, AXIS2_FAILURE); AXIS2_INTF_TO_IMPL(client)->timeout = timeout_ms; return AXIS2_SUCCESS; } int AXIS2_CALL axis2_http_client_get_timeout (axis2_http_client_t *client, axis2_env_t **env) { AXIS2_FUNC_PARAM_CHECK(client, env, AXIS2_CRTICAL_FAILURE); return AXIS2_INTF_TO_IMPL(client)->timeout; }
