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