92107b6e4055a099f2b4d4c184bb15c6131c8fcb
[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                 return -1;
138         }
139
140         // construct HTTP request
141         sprintf(request_buf, "POST %s HTTP/1.0\r\n"
142                         "Host: %s\r\n"
143                         "Content-Type: application/json\r\n"
144                         "Content-Length: %lu\r\n"
145                         "Connection: close\r\n\r\n"
146                         "%s",
147                         url, ipstr, strlen(json_request), json_request);
148
149         write(sockfd, request_buf, strlen(request_buf));
150
151         // retrive HTTP response
152         char* write_pos = response_buf;
153         while ((n = read(sockfd, write_pos, MAX_HTTP_REQUEST)) > 0)
154                 write_pos += n;
155         *write_pos = '\0';
156         close(sockfd);
157
158         // parse HTTP header
159         char* header_line = strtok(response_buf, "\r\n");
160         int ver1, ver2;
161
162         // extract http response code
163         sscanf (header_line, "HTTP/%d.%d %d %s", &ver1, &ver2, http_code, temp_buf);
164
165         return 0;
166 }
167
168
169 // perform HTTP POST request ignoring the response
170 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) {
171         int sockfd;
172         struct sockaddr_in servaddr;
173         char request_buf[MAX_HTTP_REQUEST];
174         char response_buf[MAX_HTTP_REQUEST];
175         char temp_buf[MAX_HTTP_REQUEST];
176         int n;
177
178         char ipstr[16];
179         inet_ntop(AF_INET, &addr.ip, ipstr, INET_ADDRSTRLEN);
180
181         sockfd = socket(AF_INET, SOCK_STREAM, 0);
182         if (!sockfd) {
183                 fprintf(stderr, "Unable to create socket for HTTP connection\n");
184                 return -1;
185         }
186
187         bzero(&servaddr, sizeof(servaddr));
188         servaddr.sin_family = AF_INET;
189         servaddr.sin_port = addr.port;
190         servaddr.sin_addr.s_addr = addr.ip;
191
192         if (connect(sockfd, (sockaddr*)&servaddr, sizeof(servaddr))) {
193                 fprintf(stderr, "Unable to connect to HTTP server\n");
194                 return -1;
195         }
196
197         // construct HTTP request
198         if(strlen(extra_headers)==0){
199                 sprintf(request_buf, "POST %s HTTP/1.0\r\n"
200                         "Host: %s\r\n"
201                         "Content-Type: application/json\r\n"
202                         "Content-Length: %lu\r\n"
203                         "\r\n"
204                         "%s",
205                         url, ipstr, strlen(json_request), json_request);
206         }else{
207                 sprintf(request_buf, "POST %s HTTP/1.0\r\n"
208                         "Host: %s\r\n"
209                         "Content-Type: application/json\r\n"
210                         "Content-Length: %lu\r\n"
211                         "%s\r\n\r\n"
212                         "%s",
213                         url, ipstr, strlen(json_request), extra_headers, json_request);
214         }
215
216         write(sockfd, request_buf, strlen(request_buf));
217
218         // retrive HTTP response
219         char* write_pos = response_buf;
220         while ((n = read(sockfd, write_pos, MAX_HTTP_REQUEST)) > 0)
221                 write_pos += n;
222         *write_pos = '\0';
223         close(sockfd);
224         if(write_pos==response_buf){
225                 fprintf(stderr,"Empty response from HTTP server.\n");
226                 return -1;
227         }
228
229         // parse HTTP header
230         char* header_line = strtok(response_buf, "\r\n");
231         if(header_line==NULL){
232                 fprintf(stderr,"unparseable response from HTTP server.\n");
233                 return -1;
234         }
235         int ver1, ver2;
236
237         // extract http response code
238         sscanf (header_line, "HTTP/%d.%d %d %s", &ver1, &ver2, http_code, temp_buf);
239
240         return 0;
241 }