DABC (Data Acquisition Backbone Core)  2.9.9
FastCgi.cxx
Go to the documentation of this file.
1 // $Id: FastCgi.cxx 4614 2020-11-12 13:51:49Z linev $
2 
3 /************************************************************
4  * The Data Acquisition Backbone Core (DABC) *
5  ************************************************************
6  * Copyright (C) 2009 - *
7  * GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
8  * Planckstr. 1, 64291 Darmstadt, Germany *
9  * Contact: http://dabc.gsi.de *
10  ************************************************************
11  * This software can be used under the GPL license *
12  * agreements as stated in LICENSE.txt file *
13  * which is part of the distribution. *
14  ************************************************************/
15 
16 #include "http/FastCgi.h"
17 
18 #include <cstring>
19 #include <unistd.h>
20 
21 #ifndef DABC_WITHOUT_FASTCGI
22 
23 #include "fcgiapp.h"
24 #include <fstream>
25 
26 
27 void FCGX_DABC_send_file(FCGX_Request* request, const char* fname)
28 {
29  std::ifstream is(fname);
30 
31  char* buf = 0;
32  int length = 0;
33 
34  if (is) {
35  is.seekg (0, is.end);
36  length = is.tellg();
37  is.seekg (0, is.beg);
38 
39  buf = (char*) malloc(length);
40  is.read(buf, length);
41  if (!is) {
42  free(buf);
43  buf = 0; length = 0;
44  }
45  }
46 
47  if (buf==0) {
48  FCGX_FPrintF(request->out,
49  "Status: 404 Not Found\r\n"
50  "Content-Length: 0\r\n" // Always set Content-Length
51  "Connection: close\r\n\r\n");
52  } else {
53 
54 /* char sbuf[100], etag[100];
55  time_t curtime = time(NULL);
56  strftime(sbuf, sizeof(sbuf), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&curtime));
57  snprintf(etag, sizeof(etag), "\"%lx.%ld\"",
58  (unsigned long) curtime, (long) length);
59 
60  // Send HTTP reply to the client
61  FCGX_FPrintF(request->out,
62  "HTTP/1.1 200 OK\r\n"
63  "Date: %s\r\n"
64  "Last-Modified: %s\r\n"
65  "Etag: %s\r\n"
66  "Content-Type: %s\r\n"
67  "Content-Length: %d\r\n" // Always set Content-Length
68  "\r\n", sbuf, sbuf, etag, FCGX_mime_type(fname), length);
69 
70 */
71  FCGX_FPrintF(request->out,
72  "Status: 200 OK\r\n"
73  "Content-Type: %s\r\n"
74  "Content-Length: %d\r\n" // Always set Content-Length
75  "\r\n", http::Server::GetMimeType(fname), length);
76 
77  FCGX_PutStr(buf, length, request->out);
78 
79  free(buf);
80  }
81 
82 }
83 
84 
85 
86 #endif
87 
88 
89 http::FastCgi::FastCgi(const std::string &name, dabc::Command cmd) :
90  http::Server(name, cmd),
91  fCgiPort(9000),
92  fDebugMode(false),
93  fSocket(0),
94  fThrd(0)
95 {
96  fCgiPort = Cfg("port", cmd).AsInt(9000);
97  fDebugMode = Cfg("debug", cmd).AsBool(false);
98 }
99 
101 {
102  if (fThrd) {
103  fThrd->Kill();
104  delete fThrd;
105  fThrd = 0;
106  }
107 
108  if (fSocket>0) {
109  // close opened socket
110  close(fSocket);
111  fSocket = 0;
112  }
113 }
114 
115 
117 {
119 
120  std::string sport = ":9000";
121  if (fCgiPort>0) sport = dabc::format(":%d",fCgiPort);
122 
123 #ifndef DABC_WITHOUT_FASTCGI
124  FCGX_Init();
125 
126  DOUT0("Starting FastCGI server on port %s", sport.c_str());
127 
128  fSocket = FCGX_OpenSocket(sport.c_str(), 10);
129 
130  fThrd = new dabc::PosixThread();
131  fThrd->Start(http::FastCgi::RunFunc, this);
132 
133 #else
134  EOUT("DABC compiled without FastCgi support");
135 #endif
136 
137 }
138 
139 void* http::FastCgi::RunFunc(void* args)
140 {
141 
142 #ifndef DABC_WITHOUT_FASTCGI
143 
144  http::FastCgi* server = (http::FastCgi*) args;
145 
146  FCGX_Request request;
147 
148  FCGX_InitRequest(&request, server->fSocket, 0);
149 
150  int count(0);
151 
152  while (1) {
153 
154  int rc = FCGX_Accept_r(&request);
155 
156  if (rc!=0) continue;
157 
158  count++;
159 
160  const char* inp_path = FCGX_GetParam("PATH_INFO", request.envp);
161  if (!inp_path) inp_path = FCGX_GetParam("SCRIPT_FILENAME", request.envp);
162  const char* inp_query = FCGX_GetParam("QUERY_STRING", request.envp);
163 
164  if (server->fDebugMode) {
165 
166  FCGX_FPrintF(request.out,
167  "Status: 200 OK\r\n"
168  "Content-type: text/html\r\n"
169  "\r\n"
170  "<title>FastCGI echo (fcgiapp version)</title>"
171  "<h1>FastCGI echo (fcgiapp version)</h1>\n"
172  "Request number %d<p>\n", count);
173 
174  const char *contentLength = FCGX_GetParam("CONTENT_LENGTH", request.envp);
175  int len = 0;
176 
177  if (contentLength != NULL)
178  len = strtol(contentLength, NULL, 10);
179 
180  if (len <= 0) {
181  FCGX_FPrintF(request.out, "No data from standard input.<p>\n");
182  }
183  else {
184  int i, ch;
185 
186  FCGX_FPrintF(request.out, "Standard input:<br/>\n<pre>\n");
187  for (i = 0; i < len; i++) {
188  if ((ch = FCGX_GetChar(request.in)) < 0) {
189  FCGX_FPrintF(request.out, "Error: Not enough bytes received on standard input<p>\n");
190  break;
191  }
192  FCGX_PutChar(ch, request.out);
193  }
194  FCGX_FPrintF(request.out, "\n</pre><p>\n");
195  }
196 
197  FCGX_FPrintF(request.out, "URI: %s<p>\n", inp_path);
198  FCGX_FPrintF(request.out, "QUERY: %s<p>\n", inp_query ? inp_query : "---");
199  FCGX_FPrintF(request.out, "<p>\n");
200 
201  FCGX_FPrintF(request.out, "Environment:<br/><pre>");
202  for(char** envp = request.envp; *envp != NULL; envp++) {
203  FCGX_FPrintF(request.out, "%s\n", *envp);
204  }
205  FCGX_FPrintF(request.out, "</pre><p>");
206 
207  FCGX_Finish_r(&request);
208  continue;
209  }
210 
211 
212  std::string content_type, content_header, content_str;
213  dabc::Buffer content_bin;
214 
215  if (server->IsFileRequested(inp_path, content_str)) {
216  FCGX_DABC_send_file(&request, content_str.c_str());
217  FCGX_Finish_r(&request);
218  continue;
219  }
220 
221  if (!server->Process(inp_path, inp_query,
222  content_type, content_header, content_str, content_bin)) {
223  FCGX_FPrintF(request.out, "Status: 404 Not Found\r\n"
224  "Content-Length: 0\r\n"
225  "Connection: close\r\n\r\n");
226  } else
227 
228  if (content_type=="__file__") {
229  FCGX_DABC_send_file(&request, content_str.c_str());
230  } else
231 
232  if (!content_bin.null()) {
233  FCGX_FPrintF(request.out,
234  "Status: 200 OK\r\n"
235  "Content-Type: %s\r\n"
236  "%s"
237  "Content-Length: %ld\r\n"
238  "Connection: keep-alive\r\n"
239  "\r\n",
240  content_type.c_str(),
241  content_header.c_str(),
242  content_bin.GetTotalSize());
243 
244  FCGX_PutStr((const char*) content_bin.SegmentPtr(), (long) content_bin.GetTotalSize(), request.out);
245  } else {
246 
247  // Send HTTP reply to the client
248  FCGX_FPrintF(request.out,
249  "Status: 200 OK\r\n"
250  "Content-Type: %s\r\n"
251  "%s"
252  "Content-Length: %d\r\n" // Always set Content-Length
253  "\r\n"
254  "%s",
255  content_type.c_str(),
256  content_header.c_str(),
257  content_str.length(),
258  content_str.c_str());
259  }
260 
261  FCGX_Finish_r(&request);
262 
263  } /* while */
264 
265 #endif
266 
267  return 0;
268 }
void FCGX_DABC_send_file(FCGX_Request *request, const char *fname)
Definition: FastCgi.cxx:27
Reference on memory from memory pool.
Definition: Buffer.h:135
BufferSize_t GetTotalSize() const
Return total size of all buffer segments.
Definition: Buffer.cxx:91
void * SegmentPtr(unsigned n=0) const
Returns pointer on the segment, no any boundary checks.
Definition: Buffer.h:171
Represents command with its arguments.
Definition: Command.h:99
class represents posix pthread functionality
Definition: threads.h:340
bool AsBool(bool dflt=false) const
Definition: Record.cxx:477
int64_t AsInt(int64_t dflt=0) const
Definition: Record.cxx:501
bool null() const
Returns true if reference contains nullptr.
Definition: Reference.h:151
virtual void OnThreadAssigned()
Definition: Worker.h:392
RecordField Cfg(const std::string &name, Command cmd=nullptr) const
Returns configuration field of specified name Configuration value of specified name searched in follo...
Definition: Worker.cxx:521
Server provides fastcgi access to DABC
Definition: FastCgi.h:33
int fCgiPort
configured fast cgi port, default 9000
Definition: FastCgi.h:35
bool fDebugMode
when true, only debug info returned by server
Definition: FastCgi.h:36
virtual void OnThreadAssigned()
Definition: FastCgi.cxx:116
int fSocket
fastcgi server socket
Definition: FastCgi.h:37
virtual ~FastCgi()
Definition: FastCgi.cxx:100
static void * RunFunc(void *arg)
Definition: FastCgi.cxx:139
FastCgi(const std::string &name, dabc::Command cmd=nullptr)
Definition: FastCgi.cxx:89
Server provides http access to DABC
Definition: Server.h:31
bool IsFileRequested(const char *uri, std::string &fname)
Check if file is requested.
Definition: Server.cxx:207
bool Process(const char *uri, const char *query, std::string &content_type, std::string &content_header, std::string &content_str, dabc::Buffer &content_bin)
Method process different URL requests, should be called from server thread.
Definition: Server.cxx:259
static const char * GetMimeType(const char *fname)
Definition: Server.cxx:27
#define DOUT0(args ...)
Definition: logging.h:156
#define EOUT(args ...)
Definition: logging.h:150
std::string format(const char *fmt,...)
Definition: string.cxx:49
Support of HTTP in DABC.
Definition: Civetweb.h:25