1 /* ------------------------------------------------
2 Copyright 2014 AT&T Intellectual Property
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
7 http://www.apache.org/licenses/LICENSE-2.0
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ------------------------------------------- */
16 #include <arpa/inet.h>
17 #include <netinet/in.h>
21 #include <sys/types.h>
22 #include <sys/socket.h>
27 #include "simple_http.h"
29 #define MAX_HTTP_REQUEST 64 * 1024
32 // perform HTTP GET and retrieve the json response
33 int http_get_request(endpoint addr, gs_csp_t url, gs_uint32_t* http_code, gs_sp_t json_response) {
36 struct sockaddr_in servaddr;
37 char request_buf[MAX_HTTP_REQUEST];
38 char response_buf[MAX_HTTP_REQUEST];
39 char temp_buf[MAX_HTTP_REQUEST];
40 char content_type[MAX_HTTP_REQUEST];
44 inet_ntop(AF_INET, &addr.ip, ipstr, INET_ADDRSTRLEN);
46 sockfd = socket(AF_INET, SOCK_STREAM, 0);
48 fprintf(stderr, "Unable to create socket for HTTP connection\n");
52 bzero(&servaddr, sizeof(servaddr));
53 servaddr.sin_family = AF_INET;
54 servaddr.sin_port = addr.port;
55 servaddr.sin_addr.s_addr = addr.ip;
57 if (connect(sockfd, (sockaddr*)&servaddr, sizeof(servaddr))) {
58 fprintf(stderr, "Unable to connect to HTTP server\n");
63 // construct HTTP request
64 sprintf(request_buf, "GET %s HTTP/1.0\r\n"
66 "Accept: application/json\r\n"
67 "Connection: close\r\n\r\n",
70 write(sockfd, request_buf, strlen(request_buf));
72 // retrive HTTP response
73 char* write_pos = response_buf;
74 while ((n = read(sockfd, write_pos, MAX_HTTP_REQUEST)) > 0)
79 // split HTTP response into header and the main body
80 char* header_end = strstr(response_buf, "\r\n\r\n");
82 strcpy(json_response, header_end + 4);
85 char* header_line = strtok(response_buf, "\r\n");
88 // extract http response code
89 sscanf (header_line, "HTTP/%d.%d %d %s", &ver1, &ver2, http_code, temp_buf);
91 // extract content-type
93 while ((header_line = strtok(NULL, "\r\n"))) {
94 if (!strncmp(header_line, "Content-Type: ", strlen("Content-Type: "))) {
95 strcpy(content_type, header_line + strlen("Content-Type: "));
96 if (strcmp(content_type, "application/json")) {
97 fprintf(stderr, "Invalid Content-Type %s, application/json expected\n", content_type);
100 break; // we only care about Content-Type headers
104 if ((*http_code == 200) && (*content_type == 0)) {
105 fprintf(stderr, "Missing Content-Type in server response, application/json expected\n");
113 // perform HTTP POST request ignoring the response
114 int http_post_request(endpoint addr, gs_csp_t url, gs_sp_t json_request, gs_uint32_t* http_code) {
116 struct sockaddr_in servaddr;
117 char request_buf[MAX_HTTP_REQUEST];
118 char response_buf[MAX_HTTP_REQUEST];
119 char temp_buf[MAX_HTTP_REQUEST];
123 inet_ntop(AF_INET, &addr.ip, ipstr, INET_ADDRSTRLEN);
125 sockfd = socket(AF_INET, SOCK_STREAM, 0);
127 fprintf(stderr, "Unable to create socket for HTTP connection\n");
131 bzero(&servaddr, sizeof(servaddr));
132 servaddr.sin_family = AF_INET;
133 servaddr.sin_port = addr.port;
134 servaddr.sin_addr.s_addr = addr.ip;
136 if (connect(sockfd, (sockaddr*)&servaddr, sizeof(servaddr))) {
137 fprintf(stderr, "Unable to connect to HTTP server\n");
142 // construct HTTP request
143 sprintf(request_buf, "POST %s HTTP/1.0\r\n"
145 "Content-Type: application/json\r\n"
146 "Content-Length: %lu\r\n"
147 "Connection: close\r\n\r\n"
149 url, ipstr, strlen(json_request), json_request);
151 write(sockfd, request_buf, strlen(request_buf));
153 // retrive HTTP response
154 char* write_pos = response_buf;
155 while ((n = read(sockfd, write_pos, MAX_HTTP_REQUEST)) > 0)
161 char* header_line = strtok(response_buf, "\r\n");
164 // extract http response code
165 sscanf (header_line, "HTTP/%d.%d %d %s", &ver1, &ver2, http_code, temp_buf);
171 // perform HTTP POST request ignoring the response
172 int http_post_request_hdr(endpoint addr, gs_csp_t url, gs_sp_t json_request, gs_uint32_t* http_code, gs_sp_t extra_headers) {
174 struct sockaddr_in servaddr;
175 char request_buf[MAX_HTTP_REQUEST];
176 char response_buf[MAX_HTTP_REQUEST];
177 char temp_buf[MAX_HTTP_REQUEST];
181 inet_ntop(AF_INET, &addr.ip, ipstr, INET_ADDRSTRLEN);
183 sockfd = socket(AF_INET, SOCK_STREAM, 0);
185 fprintf(stderr, "Unable to create socket for HTTP connection\n");
189 bzero(&servaddr, sizeof(servaddr));
190 servaddr.sin_family = AF_INET;
191 servaddr.sin_port = addr.port;
192 servaddr.sin_addr.s_addr = addr.ip;
194 if (connect(sockfd, (sockaddr*)&servaddr, sizeof(servaddr))) {
195 fprintf(stderr, "Unable to connect to HTTP server\n");
200 // construct HTTP request
201 if(strlen(extra_headers)==0){
202 sprintf(request_buf, "POST %s HTTP/1.0\r\n"
204 "Content-Type: application/json\r\n"
205 "Content-Length: %lu\r\n"
208 url, ipstr, strlen(json_request), json_request);
210 sprintf(request_buf, "POST %s HTTP/1.0\r\n"
212 "Content-Type: application/json\r\n"
213 "Content-Length: %lu\r\n"
216 url, ipstr, strlen(json_request), extra_headers, json_request);
219 write(sockfd, request_buf, strlen(request_buf));
221 // retrive HTTP response
222 char* write_pos = response_buf;
223 while ((n = read(sockfd, write_pos, MAX_HTTP_REQUEST)) > 0)
227 if(write_pos==response_buf){
228 fprintf(stderr,"Empty response from HTTP server.\n");
233 char* header_line = strtok(response_buf, "\r\n");
234 if(header_line==NULL){
235 fprintf(stderr,"unparseable response from HTTP server.\n");
240 // extract http response code
241 sscanf (header_line, "HTTP/%d.%d %d %s", &ver1, &ver2, http_code, temp_buf);