fastcgi++
request.cpp
Go to the documentation of this file.
1 
2 /***************************************************************************
3 * Copyright (C) 2007 Eddie Carle [eddie@erctech.org] *
4 * *
5 * This file is part of fastcgi++. *
6 * *
7 * fastcgi++ is free software: you can redistribute it and/or modify it *
8 * under the terms of the GNU Lesser General Public License as published *
9 * by the Free Software Foundation, either version 3 of the License, or (at *
10 * your option) any later version. *
11 * *
12 * fastcgi++ is distributed in the hope that it will be useful, but WITHOUT *
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
15 * License for more details. *
16 * *
17 * You should have received a copy of the GNU Lesser General Public License *
18 * along with fastcgi++. If not, see <http://www.gnu.org/licenses/>. *
19 ****************************************************************************/
20 
21 #include <fastcgi++/request.hpp>
22 
25 template<class charT> void Fastcgipp::Request<charT>::complete()
26 {
27  using namespace Protocol;
28  out.flush();
29  err.flush();
30 
31  Block buffer(transceiver->requestWrite(sizeof(Header)+sizeof(EndRequest)));
32 
33  Header& header=*(Header*)buffer.data;
34  header.setVersion(Protocol::version);
35  header.setType(END_REQUEST);
36  header.setRequestId(id.fcgiId);
37  header.setContentLength(sizeof(EndRequest));
38  header.setPaddingLength(0);
39 
40  EndRequest& body=*(EndRequest*)(buffer.data+sizeof(Header));
41  body.setAppStatus(0);
42  body.setProtocolStatus(REQUEST_COMPLETE);
43 
44  transceiver->secureWrite(sizeof(Header)+sizeof(EndRequest), id, killCon);
45 }
46 
47 template bool Fastcgipp::Request<char>::handler();
49 template<class charT> bool Fastcgipp::Request<charT>::handler()
50 {
51  using namespace Protocol;
52  using namespace std;
53 
54  try
55  {
56  if(!(role()==RESPONDER || role()==AUTHORIZER))
57  {
58  Block buffer(transceiver->requestWrite(sizeof(Header)+sizeof(EndRequest)));
59 
60  Header& header=*(Header*)buffer.data;
61  header.setVersion(Protocol::version);
62  header.setType(END_REQUEST);
63  header.setRequestId(id.fcgiId);
64  header.setContentLength(sizeof(EndRequest));
65  header.setPaddingLength(0);
66 
67  EndRequest& body=*(EndRequest*)(buffer.data+sizeof(Header));
68  body.setAppStatus(0);
69  body.setProtocolStatus(UNKNOWN_ROLE);
70 
71  transceiver->secureWrite(sizeof(Header)+sizeof(EndRequest), id, killCon);
72  return true;
73  }
74 
75  {
76  boost::lock_guard<boost::mutex> lock(messages);
77  m_message=messages.front();
78  messages.pop();
79  }
80 
81  if(message().type==0)
82  {
83  const Header& header=*(Header*)message().data.get();
84  const char* body=message().data.get()+sizeof(Header);
85  switch(header.getType())
86  {
87  case PARAMS:
88  {
89  if(state!=PARAMS) throw Exceptions::RecordsOutOfOrder();
90  if(header.getContentLength()==0)
91  {
92  if(m_maxPostSize && environment().contentLength > m_maxPostSize)
93  {
94  bigPostErrorHandler();
95  complete();
96  return true;
97  }
98  state=IN;
99  break;
100  }
101  m_environment.fill(body, header.getContentLength());
102  break;
103  }
104 
105  case IN:
106  {
107  if(state!=IN) throw Exceptions::RecordsOutOfOrder();
108  if(header.getContentLength()==0)
109  {
110  // Process POST data based on what our incoming content type is
111  if(m_environment.requestMethod == Http::HTTP_METHOD_POST)
112  {
113  const char multipart[] = "multipart/form-data";
114  const char urlEncoded[] = "application/x-www-form-urlencoded";
115 
116  if(sizeof(multipart)-1 == m_environment.contentType.size() && equal(multipart, multipart+sizeof(multipart)-1, m_environment.contentType.begin()))
117  m_environment.parsePostsMultipart();
118 
119  else if(sizeof(urlEncoded)-1 == m_environment.contentType.size() && equal(urlEncoded, urlEncoded+sizeof(urlEncoded)-1, m_environment.contentType.begin()))
120  m_environment.parsePostsUrlEncoded();
121 
122  else
124  }
125 
126  m_environment.clearPostBuffer();
127  state=OUT;
128  if(response())
129  {
130  complete();
131  return true;
132  }
133  break;
134  }
135 
136  if(!m_environment.fillPostBuffer(body, header.getContentLength()))
137  {
138  bigPostErrorHandler();
139  complete();
140  return true;
141  }
142 
143  inHandler(header.getContentLength());
144  break;
145  }
146 
147  case ABORT_REQUEST:
148  {
149  return true;
150  }
151  }
152  }
153  else if(response())
154  {
155  complete();
156  return true;
157  }
158  }
159  catch(const std::exception& e)
160  {
161  errorHandler(e);
162  complete();
163  return true;
164  }
165  return false;
166 }
167 
168 template void Fastcgipp::Request<char>::errorHandler(const std::exception& error);
169 template void Fastcgipp::Request<wchar_t>::errorHandler(const std::exception& error);
170 template<class charT> void Fastcgipp::Request<charT>::errorHandler(const std::exception& error)
171 {
172  out << \
173 "Status: 500 Internal Server Error\n"\
174 "Content-Type: text/html; charset=ISO-8859-1\r\n\r\n"\
175 "<!DOCTYPE html>"\
176 "<html lang='en'>"\
177  "<head>"\
178  "<title>500 Internal Server Error</title>"\
179  "</head>"\
180  "<body>"\
181  "<h1>500 Internal Server Error</h1>"\
182  "</body>"\
183 "</html>";
184 
185  err << '"' << error.what() << '"' << " from \"http://" << environment().host << environment().requestUri << "\" with a " << environment().requestMethod << " request method.";
186 }
187 
191 {
192  out << \
193 "Status: 413 Request Entity Too Large\n"\
194 "Content-Type: text/html; charset=ISO-8859-1\r\n\r\n"\
195 "<!DOCTYPE html>"\
196 "<html lang='en'>"\
197  "<head>"\
198  "<title>413 Request Entity Too Large</title>"\
199  "</head>"\
200  "<body>"\
201  "<h1>413 Request Entity Too Large</h1>"\
202  "</body>"\
203 "</html>";
204 }