26 #ifndef HTTP_WITHOUT_FASTCGI
32 void FCGX_ROOT_send_file(FCGX_Request *request,
const char *fname)
34 std::string buf = THttpServer::ReadFileContent(fname);
37 FCGX_FPrintF(request->out,
38 "Status: 404 Not Found\r\n"
39 "Content-Length: 0\r\n"
40 "Connection: close\r\n\r\n");
43 FCGX_FPrintF(request->out,
45 "Content-Type: %s\r\n"
46 "Content-Length: %d\r\n"
48 THttpServer::GetMimeType(fname), (
int) buf.length());
50 FCGX_PutStr(buf.c_str(), buf.length(), request->out);
97 : THttpEngine(
"fastcgi",
"fastcgi interface to webserver"), fSocket(0), fDebugMode(kFALSE), fTopName(),
98 fThrd(nullptr), fTerminating(kFALSE)
105 TFastCgi::~TFastCgi()
107 fTerminating = kTRUE;
127 Bool_t TFastCgi::Create(
const char *args)
129 #ifndef HTTP_WITHOUT_FASTCGI
132 TString sport =
":9000";
134 if ((args != 0) && (strlen(args) > 0)) {
138 while ((*args != 0) && (*args >=
'0') && (*args <=
'9'))
139 sport.Append(*args++);
142 while ((*args != 0) && (*args !=
'?'))
146 TUrl url(TString::Format(
"http://localhost/folder%s", args));
152 if (url.GetValueFromOptions(
"debug") != 0)
155 const char *top = url.GetValueFromOptions(
"top");
162 Info(
"Create",
"Starting FastCGI server on port %s", sport.Data() + 1);
164 fSocket = FCGX_OpenSocket(sport.Data(), 10);
165 fThrd =
new TThread(
"FastCgiThrd", TFastCgi::run_func,
this);
171 Error(
"Create",
"ROOT compiled without fastcgi support");
178 void *TFastCgi::run_func(
void *args)
180 #ifndef HTTP_WITHOUT_FASTCGI
182 TFastCgi *engine = (TFastCgi *)args;
184 FCGX_Request request;
186 FCGX_InitRequest(&request, engine->GetSocket(), 0);
190 while (!engine->fTerminating) {
192 int rc = FCGX_Accept_r(&request);
199 const char *inp_path = FCGX_GetParam(
"PATH_INFO", request.envp);
200 const char *inp_query = FCGX_GetParam(
"QUERY_STRING", request.envp);
201 const char *inp_method = FCGX_GetParam(
"REQUEST_METHOD", request.envp);
202 const char *inp_length = FCGX_GetParam(
"CONTENT_LENGTH", request.envp);
204 auto arg = std::make_shared<THttpCallArg>();
206 arg->SetPathAndFileName(inp_path);
208 arg->SetQuery(inp_query);
210 arg->SetMethod(inp_method);
211 if (engine->fTopName.Length() > 0)
212 arg->SetTopName(engine->fTopName.Data());
215 len = strtol(inp_length, NULL, 10);
219 int nread = FCGX_GetStr((
char *)buf.data(), len, request.in);
221 arg->SetPostData(std::move(buf));
225 for (
char **envp = request.envp; *envp != NULL; envp++) {
226 TString entry = *envp;
227 for (Int_t n = 0; n < entry.Length(); n++)
228 if (entry[n] ==
'=') {
232 header.Append(entry);
233 header.Append(
"\r\n");
235 arg->SetRequestHeader(header);
237 TString username = arg->GetRequestHeader(
"REMOTE_USER");
238 if ((username.Length() > 0) && (arg->GetRequestHeader(
"AUTH_TYPE").Length() > 0))
239 arg->SetUserName(username);
241 if (engine->fDebugMode) {
242 FCGX_FPrintF(request.out,
"Status: 200 OK\r\n"
243 "Content-type: text/html\r\n"
245 "<title>FastCGI echo</title>"
246 "<h1>FastCGI echo</h1>\n");
248 FCGX_FPrintF(request.out,
"Request %d:<br/>\n<pre>\n", count);
249 FCGX_FPrintF(request.out,
" Method : %s\n", arg->GetMethod());
250 FCGX_FPrintF(request.out,
" PathName : %s\n", arg->GetPathName());
251 FCGX_FPrintF(request.out,
" FileName : %s\n", arg->GetFileName());
252 FCGX_FPrintF(request.out,
" Query : %s\n", arg->GetQuery());
253 FCGX_FPrintF(request.out,
" PostData : %ld\n", arg->GetPostDataLength());
254 FCGX_FPrintF(request.out,
"</pre><p>\n");
256 FCGX_FPrintF(request.out,
"Environment:<br/>\n<pre>\n");
257 for (
char **envp = request.envp; *envp != NULL; envp++) {
258 FCGX_FPrintF(request.out,
" %s\n", *envp);
260 FCGX_FPrintF(request.out,
"</pre><p>\n");
262 FCGX_Finish_r(&request);
268 if (engine->GetServer()->IsFileRequested(inp_path, fname)) {
269 FCGX_ROOT_send_file(&request, fname.Data());
270 FCGX_Finish_r(&request);
274 if (!engine->GetServer()->ExecuteHttp(arg) || arg->Is404()) {
275 std::string hdr = arg->FillHttpHeader(
"Status:");
276 FCGX_FPrintF(request.out, hdr.c_str());
277 }
else if (arg->IsFile()) {
278 FCGX_ROOT_send_file(&request, (
const char *)arg->GetContent());
282 if (arg->GetZipping() != THttpCallArg::kNoZip)
283 arg->CompressWithGzip();
285 std::string hdr = arg->FillHttpHeader(
"Status:");
286 FCGX_FPrintF(request.out, hdr.c_str());
288 FCGX_PutStr((
const char *)arg->GetContent(), (int)arg->GetContentLength(), request.out);
291 FCGX_Finish_r(&request);