c4f8bdd39e841525cf0a68ccff969611ac7a77b0
[com/gs-lite.git] / src / lib / gscpaux / simple_http.cpp
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
6
7      http://www.apache.org/licenses/LICENSE-2.0
8
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  ------------------------------------------- */
15
16 #include <arpa/inet.h>
17 #include <netinet/in.h>
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include <sys/types.h>
22 #include <sys/socket.h>
23 #include <sys/wait.h>
24 #include <netdb.h>
25 #include <unistd.h>
26
27 #include "simple_http.h"
28
29 #define MAX_HTTP_REQUEST 64 * 1024
30
31
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) {
34
35         int sockfd;
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];
41         int n;
42
43         char ipstr[16];
44         inet_ntop(AF_INET, &addr.ip, ipstr, INET_ADDRSTRLEN);
45
46         sockfd = socket(AF_INET, SOCK_STREAM, 0);
47         if (!sockfd) {
48                 fprintf(stderr, "Unable to create socket for HTTP connection\n");
49                 return -1;
50         }
51
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;
56
57         if (connect(sockfd, (sockaddr*)&servaddr, sizeof(servaddr))) {
58                 fprintf(stderr, "Unable to connect to HTTP server\n");
59                 return -1;
60         }
61
62         // construct HTTP request
63         sprintf(request_buf, "GET %s HTTP/1.0\r\n"
64                         "Host: %s\r\n"
65                         "Accept: application/json\r\n"
66                         "Connection: close\r\n\r\n",
67                         url, ipstr);
68
69         write(sockfd, request_buf, strlen(request_buf));
70
71         // retrive HTTP response
72         char* write_pos = response_buf;
73         while ((n = read(sockfd, write_pos, MAX_HTTP_REQUEST)) > 0)
74                 write_pos += n;
75         *write_pos = '\0';
76         close(sockfd);
77
78         // split HTTP response into header and the main body
79         char* header_end = strstr(response_buf, "\r\n\r\n");
80         *header_end = 0;
81         strcpy(json_response, header_end + 4);
82
83         // parse HTTP header
84         char* header_line = strtok(response_buf, "\r\n");
85         int ver1, ver2;
86
87         // extract http response code
88         sscanf (header_line, "HTTP/%d.%d %d %s", &ver1, &ver2, http_code, temp_buf);
89
90         // extract content-type
91         *content_type = 0;
92         while ((header_line = strtok(NULL, "\r\n"))) {
93                 if (!strncmp(header_line, "Content-Type: ", strlen("Content-Type: "))) {
94                         strcpy(content_type, header_line + strlen("Content-Type: "));
95                         if (strcmp(content_type, "application/json")) {
96                                 fprintf(stderr, "Invalid Content-Type %s, application/json expected\n", content_type);
97                                 return -1;
98                         }
99                         break;          // we only care about Content-Type headers
100                 }
101         }
102
103         if ((*http_code == 200) && (*content_type == 0)) {
104                 fprintf(stderr, "Missing Content-Type in server response, application/json expected\n");
105                 return -1;
106         }
107
108
109         return 0;
110 }
111
112 // perform HTTP POST request ignoring the response
113 int http_post_request(endpoint addr, gs_csp_t url, gs_sp_t json_request, gs_uint32_t* http_code) {
114         int sockfd;
115         struct sockaddr_in servaddr;
116         char request_buf[MAX_HTTP_REQUEST];
117         char response_buf[MAX_HTTP_REQUEST];
118         char temp_buf[MAX_HTTP_REQUEST];
119         int n;
120
121         char ipstr[16];
122         inet_ntop(AF_INET, &addr.ip, ipstr, INET_ADDRSTRLEN);
123
124         sockfd = socket(AF_INET, SOCK_STREAM, 0);
125         if (!sockfd) {
126                 fprintf(stderr, "Unable to create socket for HTTP connection\n");
127                 return -1;
128         }
129
130         bzero(&servaddr, sizeof(servaddr));
131         servaddr.sin_family = AF_INET;
132         servaddr.sin_port = addr.port;
133         servaddr.sin_addr.s_addr = addr.ip;
134
135         if (connect(sockfd, (sockaddr*)&servaddr, sizeof(servaddr))) {
136                 fprintf(stderr, "Unable to connect to HTTP server\n");
137                 close(sockfd);
138                 return -1;
139         }
140
141         // construct HTTP request
142         sprintf(request_buf, "POST %s HTTP/1.0\r\n"
143                         "Host: %s\r\n"
144                         "Content-Type: application/json\r\n"
145                         "Content-Length: %lu\r\n"
146                         "Connection: close\r\n\r\n"
147                         "%s",
148                         url, ipstr, strlen(json_request), json_request);
149
150         write(sockfd, request_buf, strlen(request_buf));
151
152         // retrive HTTP response
153         char* write_pos = response_buf;
154         while ((n = read(sockfd, write_pos, MAX_HTTP_REQUEST)) > 0)
155                 write_pos += n;
156         *write_pos = '\0';
157         close(sockfd);
158
159         // parse HTTP header
160         char* header_line = strtok(response_buf, "\r\n");
161         int ver1, ver2;
162
163         // extract http response code
164         sscanf (header_line, "HTTP/%d.%d %d %s", &ver1, &ver2, http_code, temp_buf);
165
166         return 0;
167 }
168
169
170 // perform HTTP POST request ignoring the response
171 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) {
172         int sockfd;
173         struct sockaddr_in servaddr;
174         char request_buf[MAX_HTTP_REQUEST];
175         char response_buf[MAX_HTTP_REQUEST];
176         char temp_buf[MAX_HTTP_REQUEST];
177         int n;
178
179         char ipstr[16];
180         inet_ntop(AF_INET, &addr.ip, ipstr, INET_ADDRSTRLEN);
181
182         sockfd = socket(AF_INET, SOCK_STREAM, 0);
183         if (!sockfd) {
184                 fprintf(stderr, "Unable to create socket for HTTP connection\n");
185                 return -1;
186         }
187
188         bzero(&servaddr, sizeof(servaddr));
189         servaddr.sin_family = AF_INET;
190         servaddr.sin_port = addr.port;
191         servaddr.sin_addr.s_addr = addr.ip;
192
193         if (connect(sockfd, (sockaddr*)&servaddr, sizeof(servaddr))) {
194                 fprintf(stderr, "Unable to connect to HTTP server\n");
195                 return -1;
196         }
197
198         // construct HTTP request
199         if(strlen(extra_headers)==0){
200                 sprintf(request_buf, "POST %s HTTP/1.0\r\n"
201                         "Host: %s\r\n"
202                         "Content-Type: application/json\r\n"
203                         "Content-Length: %lu\r\n"
204                         "\r\n"
205                         "%s",
206                         url, ipstr, strlen(json_request), json_request);
207         }else{
208                 sprintf(request_buf, "POST %s HTTP/1.0\r\n"
209                         "Host: %s\r\n"
210                         "Content-Type: application/json\r\n"
211                         "Content-Length: %lu\r\n"
212                         "%s\r\n\r\n"
213                         "%s",
214                         url, ipstr, strlen(json_request), extra_headers, json_request);
215         }
216
217         write(sockfd, request_buf, strlen(request_buf));
218
219         // retrive HTTP response
220         char* write_pos = response_buf;
221         while ((n = read(sockfd, write_pos, MAX_HTTP_REQUEST)) > 0)
222                 write_pos += n;
223         *write_pos = '\0';
224         close(sockfd);
225         if(write_pos==response_buf){
226                 fprintf(stderr,"Empty response from HTTP server.\n");
227                 return -1;
228         }
229
230         // parse HTTP header
231         char* header_line = strtok(response_buf, "\r\n");
232         if(header_line==NULL){
233                 fprintf(stderr,"unparseable response from HTTP server.\n");
234                 return -1;
235         }
236         int ver1, ver2;
237
238         // extract http response code
239         sscanf (header_line, "HTTP/%d.%d %d %s", &ver1, &ver2, http_code, temp_buf);
240
241         return 0;
242 }