PageRenderTime 28ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/projects/tomcat-7.0.2/java/org/apache/coyote/http11/Http11Processor.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 1063 lines | 703 code | 172 blank | 188 comment | 271 complexity | 75fbab5c4ddecfc333402f6ebf425ca4 MD5 | raw file
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. package org.apache.coyote.http11;
  18. import java.io.IOException;
  19. import java.io.InterruptedIOException;
  20. import java.net.InetAddress;
  21. import java.net.Socket;
  22. import java.util.Locale;
  23. import java.util.concurrent.atomic.AtomicBoolean;
  24. import org.apache.coyote.ActionCode;
  25. import org.apache.coyote.ActionHook;
  26. import org.apache.coyote.Request;
  27. import org.apache.coyote.RequestInfo;
  28. import org.apache.coyote.Response;
  29. import org.apache.coyote.http11.filters.BufferedInputFilter;
  30. import org.apache.coyote.http11.filters.SavedRequestInputFilter;
  31. import org.apache.juli.logging.Log;
  32. import org.apache.juli.logging.LogFactory;
  33. import org.apache.tomcat.util.buf.ByteChunk;
  34. import org.apache.tomcat.util.buf.HexUtils;
  35. import org.apache.tomcat.util.buf.MessageBytes;
  36. import org.apache.tomcat.util.http.FastHttpDateFormat;
  37. import org.apache.tomcat.util.http.MimeHeaders;
  38. import org.apache.tomcat.util.net.JIoEndpoint;
  39. import org.apache.tomcat.util.net.SSLSupport;
  40. import org.apache.tomcat.util.net.SocketStatus;
  41. import org.apache.tomcat.util.net.SocketWrapper;
  42. import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState;
  43. /**
  44. * Processes HTTP requests.
  45. *
  46. * @author Remy Maucherat
  47. * @author fhanik
  48. */
  49. public class Http11Processor extends AbstractHttp11Processor implements ActionHook {
  50. /**
  51. * Logger.
  52. */
  53. private static final Log log = LogFactory.getLog(Http11Processor.class);
  54. // ------------------------------------------------------------ Constructor
  55. public Http11Processor(int headerBufferSize, JIoEndpoint endpoint) {
  56. this.endpoint = endpoint;
  57. request = new Request();
  58. inputBuffer = new InternalInputBuffer(request, headerBufferSize);
  59. request.setInputBuffer(inputBuffer);
  60. response = new Response();
  61. response.setHook(this);
  62. outputBuffer = new InternalOutputBuffer(response, headerBufferSize);
  63. response.setOutputBuffer(outputBuffer);
  64. request.setResponse(response);
  65. initializeFilters();
  66. // Cause loading of HexUtils
  67. HexUtils.load();
  68. }
  69. // ----------------------------------------------------- Instance Variables
  70. /**
  71. * Input.
  72. */
  73. protected InternalInputBuffer inputBuffer = null;
  74. /**
  75. * Output.
  76. */
  77. protected InternalOutputBuffer outputBuffer = null;
  78. /**
  79. * SSL information.
  80. */
  81. protected SSLSupport sslSupport;
  82. /**
  83. * Async used
  84. */
  85. protected boolean async = false;
  86. /**
  87. * State flag.
  88. */
  89. protected boolean started = false;
  90. /**
  91. * Socket associated with the current connection.
  92. */
  93. protected SocketWrapper<Socket> socket;
  94. /**
  95. * Associated endpoint.
  96. */
  97. protected JIoEndpoint endpoint;
  98. // --------------------------------------------------------- Public Methods
  99. /**
  100. * Set the SSL information for this HTTP connection.
  101. */
  102. public void setSSLSupport(SSLSupport sslSupport) {
  103. this.sslSupport = sslSupport;
  104. }
  105. /**
  106. * Process pipelined HTTP requests on the specified socket.
  107. *
  108. * @param socketWrapper Socket from which the HTTP requests will be read
  109. * and the HTTP responses will be written.
  110. *
  111. * @throws IOException error during an I/O operation
  112. */
  113. public SocketState process(SocketWrapper<Socket> socketWrapper)
  114. throws IOException {
  115. RequestInfo rp = request.getRequestProcessor();
  116. rp.setStage(org.apache.coyote.Constants.STAGE_PARSE);
  117. // Set the remote address
  118. remoteAddr = null;
  119. remoteHost = null;
  120. localAddr = null;
  121. localName = null;
  122. remotePort = -1;
  123. localPort = -1;
  124. // Setting up the I/O
  125. this.socket = socketWrapper;
  126. inputBuffer.setInputStream(socket.getSocket().getInputStream());
  127. outputBuffer.setOutputStream(socket.getSocket().getOutputStream());
  128. // Error flag
  129. error = false;
  130. keepAlive = true;
  131. int keepAliveLeft = maxKeepAliveRequests>0?socketWrapper.decrementKeepAlive():-1;
  132. int soTimeout = endpoint.getSoTimeout();
  133. try {
  134. socket.getSocket().setSoTimeout(soTimeout);
  135. } catch (Throwable t) {
  136. log.debug(sm.getString("http11processor.socket.timeout"), t);
  137. error = true;
  138. }
  139. boolean keptAlive = socketWrapper.isKeptAlive();
  140. while (started && !error && keepAlive) {
  141. // Parsing the request header
  142. try {
  143. //TODO - calculate timeout based on length in queue (System.currentTimeMills() - wrapper.getLastAccess() is the time in queue)
  144. if (keptAlive) {
  145. if (keepAliveTimeout > 0) {
  146. socket.getSocket().setSoTimeout(keepAliveTimeout);
  147. }
  148. else if (soTimeout > 0) {
  149. socket.getSocket().setSoTimeout(soTimeout);
  150. }
  151. }
  152. inputBuffer.parseRequestLine(false);
  153. request.setStartTime(System.currentTimeMillis());
  154. keptAlive = true;
  155. if (disableUploadTimeout) {
  156. socket.getSocket().setSoTimeout(soTimeout);
  157. } else {
  158. socket.getSocket().setSoTimeout(timeout);
  159. }
  160. inputBuffer.parseHeaders();
  161. } catch (IOException e) {
  162. error = true;
  163. break;
  164. } catch (Throwable t) {
  165. if (log.isDebugEnabled()) {
  166. log.debug(sm.getString("http11processor.header.parse"), t);
  167. }
  168. // 400 - Bad Request
  169. response.setStatus(400);
  170. adapter.log(request, response, 0);
  171. error = true;
  172. }
  173. if (!error) {
  174. // Setting up filters, and parse some request headers
  175. rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);
  176. try {
  177. prepareRequest();
  178. } catch (Throwable t) {
  179. if (log.isDebugEnabled()) {
  180. log.debug(sm.getString("http11processor.request.prepare"), t);
  181. }
  182. // 400 - Internal Server Error
  183. response.setStatus(400);
  184. adapter.log(request, response, 0);
  185. error = true;
  186. }
  187. }
  188. if (maxKeepAliveRequests > 0 && keepAliveLeft == 0)
  189. keepAlive = false;
  190. // Process the request in the adapter
  191. if (!error) {
  192. try {
  193. rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
  194. adapter.service(request, response);
  195. // Handle when the response was committed before a serious
  196. // error occurred. Throwing a ServletException should both
  197. // set the status to 500 and set the errorException.
  198. // If we fail here, then the response is likely already
  199. // committed, so we can't try and set headers.
  200. if(keepAlive && !error) { // Avoid checking twice.
  201. error = response.getErrorException() != null ||
  202. statusDropsConnection(response.getStatus());
  203. }
  204. } catch (InterruptedIOException e) {
  205. error = true;
  206. } catch (Throwable t) {
  207. log.error(sm.getString("http11processor.request.process"), t);
  208. // 500 - Internal Server Error
  209. response.setStatus(500);
  210. adapter.log(request, response, 0);
  211. error = true;
  212. }
  213. }
  214. // Finish the handling of the request
  215. try {
  216. rp.setStage(org.apache.coyote.Constants.STAGE_ENDINPUT);
  217. // If we know we are closing the connection, don't drain input.
  218. // This way uploading a 100GB file doesn't tie up the thread
  219. // if the servlet has rejected it.
  220. if(error && !async)
  221. inputBuffer.setSwallowInput(false);
  222. if (!async)
  223. endRequest();
  224. } catch (Throwable t) {
  225. log.error(sm.getString("http11processor.request.finish"), t);
  226. // 500 - Internal Server Error
  227. response.setStatus(500);
  228. adapter.log(request, response, 0);
  229. error = true;
  230. }
  231. try {
  232. rp.setStage(org.apache.coyote.Constants.STAGE_ENDOUTPUT);
  233. } catch (Throwable t) {
  234. log.error(sm.getString("http11processor.response.finish"), t);
  235. error = true;
  236. }
  237. // If there was an error, make sure the request is counted as
  238. // and error, and update the statistics counter
  239. if (error) {
  240. response.setStatus(500);
  241. }
  242. request.updateCounters();
  243. rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE);
  244. // Don't reset the param - we'll see it as ended. Next request
  245. // will reset it
  246. // thrA.setParam(null);
  247. // Next request
  248. if (!async || error) {
  249. inputBuffer.nextRequest();
  250. outputBuffer.nextRequest();
  251. }
  252. //hack keep alive behavior
  253. break;
  254. }
  255. rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
  256. if (error) {
  257. recycle();
  258. return SocketState.CLOSED;
  259. } else if (async) {
  260. return SocketState.LONG;
  261. } else {
  262. if (!keepAlive) {
  263. recycle();
  264. return SocketState.CLOSED;
  265. } else {
  266. return SocketState.OPEN;
  267. }
  268. }
  269. }
  270. public SocketState asyncDispatch(SocketStatus status) throws IOException {
  271. RequestInfo rp = request.getRequestProcessor();
  272. try {
  273. rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
  274. error = !adapter.asyncDispatch(request, response, status);
  275. } catch (InterruptedIOException e) {
  276. error = true;
  277. } catch (Throwable t) {
  278. log.error(sm.getString("http11processor.request.process"), t);
  279. // 500 - Internal Server Error
  280. response.setStatus(500);
  281. adapter.log(request, response, 0);
  282. error = true;
  283. }
  284. rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
  285. if (error) {
  286. recycle();
  287. return SocketState.CLOSED;
  288. } else if (async) {
  289. return SocketState.LONG;
  290. } else {
  291. recycle();
  292. if (!keepAlive) {
  293. return SocketState.CLOSED;
  294. } else {
  295. return SocketState.OPEN;
  296. }
  297. }
  298. }
  299. public void endRequest() {
  300. // Finish the handling of the request
  301. try {
  302. inputBuffer.endRequest();
  303. } catch (IOException e) {
  304. error = true;
  305. } catch (Throwable t) {
  306. log.error(sm.getString("http11processor.request.finish"), t);
  307. // 500 - Internal Server Error
  308. response.setStatus(500);
  309. adapter.log(request, response, 0);
  310. error = true;
  311. }
  312. try {
  313. outputBuffer.endRequest();
  314. } catch (IOException e) {
  315. error = true;
  316. } catch (Throwable t) {
  317. log.error(sm.getString("http11processor.response.finish"), t);
  318. error = true;
  319. }
  320. }
  321. public void recycle() {
  322. // Recycle
  323. inputBuffer.recycle();
  324. outputBuffer.recycle();
  325. this.socket = null;
  326. async = false;
  327. // Recycle ssl info
  328. sslSupport = null;
  329. }
  330. // ----------------------------------------------------- ActionHook Methods
  331. /**
  332. * Send an action to the connector.
  333. *
  334. * @param actionCode Type of the action
  335. * @param param Action parameter
  336. */
  337. public void action(ActionCode actionCode, Object param) {
  338. if (actionCode == ActionCode.ACTION_COMMIT) {
  339. // Commit current response
  340. if (response.isCommitted())
  341. return;
  342. // Validate and write response headers
  343. prepareResponse();
  344. try {
  345. outputBuffer.commit();
  346. } catch (IOException e) {
  347. // Set error flag
  348. error = true;
  349. }
  350. } else if (actionCode == ActionCode.ACTION_ACK) {
  351. // Acknowledge request
  352. // Send a 100 status back if it makes sense (response not committed
  353. // yet, and client specified an expectation for 100-continue)
  354. if ((response.isCommitted()) || !expectation)
  355. return;
  356. inputBuffer.setSwallowInput(true);
  357. try {
  358. outputBuffer.sendAck();
  359. } catch (IOException e) {
  360. // Set error flag
  361. error = true;
  362. }
  363. } else if (actionCode == ActionCode.ACTION_CLIENT_FLUSH) {
  364. try {
  365. outputBuffer.flush();
  366. } catch (IOException e) {
  367. // Set error flag
  368. error = true;
  369. response.setErrorException(e);
  370. }
  371. } else if (actionCode == ActionCode.ACTION_CLOSE) {
  372. // Close
  373. async = false;
  374. // End the processing of the current request, and stop any further
  375. // transactions with the client
  376. try {
  377. outputBuffer.endRequest();
  378. } catch (IOException e) {
  379. // Set error flag
  380. error = true;
  381. }
  382. } else if (actionCode == ActionCode.ACTION_RESET) {
  383. // Reset response
  384. // Note: This must be called before the response is committed
  385. outputBuffer.reset();
  386. } else if (actionCode == ActionCode.ACTION_CUSTOM) {
  387. // Do nothing
  388. } else if (actionCode == ActionCode.ACTION_START) {
  389. started = true;
  390. } else if (actionCode == ActionCode.ACTION_STOP) {
  391. started = false;
  392. } else if (actionCode == ActionCode.ACTION_REQ_SSL_ATTRIBUTE ) {
  393. try {
  394. if (sslSupport != null) {
  395. Object sslO = sslSupport.getCipherSuite();
  396. if (sslO != null)
  397. request.setAttribute
  398. (SSLSupport.CIPHER_SUITE_KEY, sslO);
  399. sslO = sslSupport.getPeerCertificateChain(false);
  400. if (sslO != null)
  401. request.setAttribute
  402. (SSLSupport.CERTIFICATE_KEY, sslO);
  403. sslO = sslSupport.getKeySize();
  404. if (sslO != null)
  405. request.setAttribute
  406. (SSLSupport.KEY_SIZE_KEY, sslO);
  407. sslO = sslSupport.getSessionId();
  408. if (sslO != null)
  409. request.setAttribute
  410. (SSLSupport.SESSION_ID_KEY, sslO);
  411. request.setAttribute(SSLSupport.SESSION_MGR, sslSupport);
  412. }
  413. } catch (Exception e) {
  414. log.warn(sm.getString("http11processor.socket.ssl"), e);
  415. }
  416. } else if (actionCode == ActionCode.ACTION_REQ_HOST_ADDR_ATTRIBUTE) {
  417. if ((remoteAddr == null) && (socket != null)) {
  418. InetAddress inetAddr = socket.getSocket().getInetAddress();
  419. if (inetAddr != null) {
  420. remoteAddr = inetAddr.getHostAddress();
  421. }
  422. }
  423. request.remoteAddr().setString(remoteAddr);
  424. } else if (actionCode == ActionCode.ACTION_REQ_LOCAL_NAME_ATTRIBUTE) {
  425. if ((localName == null) && (socket != null)) {
  426. InetAddress inetAddr = socket.getSocket().getLocalAddress();
  427. if (inetAddr != null) {
  428. localName = inetAddr.getHostName();
  429. }
  430. }
  431. request.localName().setString(localName);
  432. } else if (actionCode == ActionCode.ACTION_REQ_HOST_ATTRIBUTE) {
  433. if ((remoteHost == null) && (socket != null)) {
  434. InetAddress inetAddr = socket.getSocket().getInetAddress();
  435. if (inetAddr != null) {
  436. remoteHost = inetAddr.getHostName();
  437. }
  438. if(remoteHost == null) {
  439. if(remoteAddr != null) {
  440. remoteHost = remoteAddr;
  441. } else { // all we can do is punt
  442. request.remoteHost().recycle();
  443. }
  444. }
  445. }
  446. request.remoteHost().setString(remoteHost);
  447. } else if (actionCode == ActionCode.ACTION_REQ_LOCAL_ADDR_ATTRIBUTE) {
  448. if (localAddr == null)
  449. localAddr = socket.getSocket().getLocalAddress().getHostAddress();
  450. request.localAddr().setString(localAddr);
  451. } else if (actionCode == ActionCode.ACTION_REQ_REMOTEPORT_ATTRIBUTE) {
  452. if ((remotePort == -1 ) && (socket !=null)) {
  453. remotePort = socket.getSocket().getPort();
  454. }
  455. request.setRemotePort(remotePort);
  456. } else if (actionCode == ActionCode.ACTION_REQ_LOCALPORT_ATTRIBUTE) {
  457. if ((localPort == -1 ) && (socket !=null)) {
  458. localPort = socket.getSocket().getLocalPort();
  459. }
  460. request.setLocalPort(localPort);
  461. } else if (actionCode == ActionCode.ACTION_REQ_SSL_CERTIFICATE) {
  462. if( sslSupport != null) {
  463. /*
  464. * Consume and buffer the request body, so that it does not
  465. * interfere with the client's handshake messages
  466. */
  467. InputFilter[] inputFilters = inputBuffer.getFilters();
  468. ((BufferedInputFilter) inputFilters[Constants.BUFFERED_FILTER])
  469. .setLimit(maxSavePostSize);
  470. inputBuffer.addActiveFilter
  471. (inputFilters[Constants.BUFFERED_FILTER]);
  472. try {
  473. Object sslO = sslSupport.getPeerCertificateChain(true);
  474. if( sslO != null) {
  475. request.setAttribute
  476. (SSLSupport.CERTIFICATE_KEY, sslO);
  477. }
  478. } catch (Exception e) {
  479. log.warn(sm.getString("http11processor.socket.ssl"), e);
  480. }
  481. }
  482. } else if (actionCode == ActionCode.ACTION_REQ_SET_BODY_REPLAY) {
  483. ByteChunk body = (ByteChunk) param;
  484. InputFilter savedBody = new SavedRequestInputFilter(body);
  485. savedBody.setRequest(request);
  486. InternalInputBuffer internalBuffer = (InternalInputBuffer)
  487. request.getInputBuffer();
  488. internalBuffer.addActiveFilter(savedBody);
  489. } else if (actionCode == ActionCode.ACTION_ASYNC_START) {
  490. //TODO SERVLET3 - async
  491. async = true;
  492. } else if (actionCode == ActionCode.ACTION_ASYNC_COMPLETE) {
  493. //TODO SERVLET3 - async
  494. AtomicBoolean dispatch = (AtomicBoolean)param;
  495. RequestInfo rp = request.getRequestProcessor();
  496. if ( rp.getStage() != org.apache.coyote.Constants.STAGE_SERVICE ) { //async handling
  497. dispatch.set(true);
  498. endpoint.processSocket(this.socket, SocketStatus.STOP);
  499. } else {
  500. dispatch.set(false);
  501. }
  502. } else if (actionCode == ActionCode.ACTION_ASYNC_SETTIMEOUT) {
  503. //TODO SERVLET3 - async
  504. if (param==null) return;
  505. long timeout = ((Long)param).longValue();
  506. //if we are not piggy backing on a worker thread, set the timeout
  507. socket.setTimeout(timeout);
  508. } else if (actionCode == ActionCode.ACTION_ASYNC_DISPATCH) {
  509. RequestInfo rp = request.getRequestProcessor();
  510. AtomicBoolean dispatch = (AtomicBoolean)param;
  511. if ( rp.getStage() != org.apache.coyote.Constants.STAGE_SERVICE ) {//async handling
  512. endpoint.processSocket(this.socket, SocketStatus.OPEN);
  513. dispatch.set(true);
  514. } else {
  515. dispatch.set(true);
  516. }
  517. }
  518. }
  519. // ------------------------------------------------------ Connector Methods
  520. // ------------------------------------------------------ Protected Methods
  521. /**
  522. * After reading the request headers, we have to setup the request filters.
  523. */
  524. protected void prepareRequest() {
  525. http11 = true;
  526. http09 = false;
  527. contentDelimitation = false;
  528. expectation = false;
  529. if (sslSupport != null) {
  530. request.scheme().setString("https");
  531. }
  532. MessageBytes protocolMB = request.protocol();
  533. if (protocolMB.equals(Constants.HTTP_11)) {
  534. http11 = true;
  535. protocolMB.setString(Constants.HTTP_11);
  536. } else if (protocolMB.equals(Constants.HTTP_10)) {
  537. http11 = false;
  538. keepAlive = false;
  539. protocolMB.setString(Constants.HTTP_10);
  540. } else if (protocolMB.equals("")) {
  541. // HTTP/0.9
  542. http09 = true;
  543. http11 = false;
  544. keepAlive = false;
  545. } else {
  546. // Unsupported protocol
  547. http11 = false;
  548. error = true;
  549. // Send 505; Unsupported HTTP version
  550. if (log.isDebugEnabled()) {
  551. log.debug(sm.getString("http11processor.request.prepare")+
  552. " Unsupported HTTP version \""+protocolMB+"\"");
  553. }
  554. response.setStatus(505);
  555. adapter.log(request, response, 0);
  556. }
  557. MessageBytes methodMB = request.method();
  558. if (methodMB.equals(Constants.GET)) {
  559. methodMB.setString(Constants.GET);
  560. } else if (methodMB.equals(Constants.POST)) {
  561. methodMB.setString(Constants.POST);
  562. }
  563. MimeHeaders headers = request.getMimeHeaders();
  564. // Check connection header
  565. MessageBytes connectionValueMB = headers.getValue("connection");
  566. if (connectionValueMB != null) {
  567. ByteChunk connectionValueBC = connectionValueMB.getByteChunk();
  568. if (findBytes(connectionValueBC, Constants.CLOSE_BYTES) != -1) {
  569. keepAlive = false;
  570. } else if (findBytes(connectionValueBC,
  571. Constants.KEEPALIVE_BYTES) != -1) {
  572. keepAlive = true;
  573. }
  574. }
  575. MessageBytes expectMB = null;
  576. if (http11)
  577. expectMB = headers.getValue("expect");
  578. if ((expectMB != null)
  579. && (expectMB.indexOfIgnoreCase("100-continue", 0) != -1)) {
  580. inputBuffer.setSwallowInput(false);
  581. expectation = true;
  582. }
  583. // Check user-agent header
  584. if ((restrictedUserAgents != null) && ((http11) || (keepAlive))) {
  585. MessageBytes userAgentValueMB = headers.getValue("user-agent");
  586. // Check in the restricted list, and adjust the http11
  587. // and keepAlive flags accordingly
  588. if(userAgentValueMB != null) {
  589. String userAgentValue = userAgentValueMB.toString();
  590. for (int i = 0; i < restrictedUserAgents.length; i++) {
  591. if (restrictedUserAgents[i].matcher(userAgentValue).matches()) {
  592. http11 = false;
  593. keepAlive = false;
  594. break;
  595. }
  596. }
  597. }
  598. }
  599. // Check for a full URI (including protocol://host:port/)
  600. ByteChunk uriBC = request.requestURI().getByteChunk();
  601. if (uriBC.startsWithIgnoreCase("http", 0)) {
  602. int pos = uriBC.indexOf("://", 0, 3, 4);
  603. int uriBCStart = uriBC.getStart();
  604. int slashPos = -1;
  605. if (pos != -1) {
  606. byte[] uriB = uriBC.getBytes();
  607. slashPos = uriBC.indexOf('/', pos + 3);
  608. if (slashPos == -1) {
  609. slashPos = uriBC.getLength();
  610. // Set URI as "/"
  611. request.requestURI().setBytes
  612. (uriB, uriBCStart + pos + 1, 1);
  613. } else {
  614. request.requestURI().setBytes
  615. (uriB, uriBCStart + slashPos,
  616. uriBC.getLength() - slashPos);
  617. }
  618. MessageBytes hostMB = headers.setValue("host");
  619. hostMB.setBytes(uriB, uriBCStart + pos + 3,
  620. slashPos - pos - 3);
  621. }
  622. }
  623. // Input filter setup
  624. InputFilter[] inputFilters = inputBuffer.getFilters();
  625. // Parse transfer-encoding header
  626. MessageBytes transferEncodingValueMB = null;
  627. if (http11)
  628. transferEncodingValueMB = headers.getValue("transfer-encoding");
  629. if (transferEncodingValueMB != null) {
  630. String transferEncodingValue = transferEncodingValueMB.toString();
  631. // Parse the comma separated list. "identity" codings are ignored
  632. int startPos = 0;
  633. int commaPos = transferEncodingValue.indexOf(',');
  634. String encodingName = null;
  635. while (commaPos != -1) {
  636. encodingName = transferEncodingValue.substring
  637. (startPos, commaPos).toLowerCase(Locale.ENGLISH).trim();
  638. if (!addInputFilter(inputFilters, encodingName)) {
  639. // Unsupported transfer encoding
  640. error = true;
  641. // 501 - Unimplemented
  642. response.setStatus(501);
  643. adapter.log(request, response, 0);
  644. }
  645. startPos = commaPos + 1;
  646. commaPos = transferEncodingValue.indexOf(',', startPos);
  647. }
  648. encodingName = transferEncodingValue.substring(startPos)
  649. .toLowerCase(Locale.ENGLISH).trim();
  650. if (!addInputFilter(inputFilters, encodingName)) {
  651. // Unsupported transfer encoding
  652. error = true;
  653. // 501 - Unimplemented
  654. if (log.isDebugEnabled()) {
  655. log.debug(sm.getString("http11processor.request.prepare")+
  656. " Unsupported transfer encoding \""+encodingName+"\"");
  657. }
  658. response.setStatus(501);
  659. adapter.log(request, response, 0);
  660. }
  661. }
  662. // Parse content-length header
  663. long contentLength = request.getContentLengthLong();
  664. if (contentLength >= 0 && !contentDelimitation) {
  665. inputBuffer.addActiveFilter
  666. (inputFilters[Constants.IDENTITY_FILTER]);
  667. contentDelimitation = true;
  668. }
  669. MessageBytes valueMB = headers.getValue("host");
  670. // Check host header
  671. if (http11 && (valueMB == null)) {
  672. error = true;
  673. // 400 - Bad request
  674. if (log.isDebugEnabled()) {
  675. log.debug(sm.getString("http11processor.request.prepare")+
  676. " host header missing");
  677. }
  678. response.setStatus(400);
  679. adapter.log(request, response, 0);
  680. }
  681. parseHost(valueMB);
  682. if (!contentDelimitation) {
  683. // If there's no content length
  684. // (broken HTTP/1.0 or HTTP/1.1), assume
  685. // the client is not broken and didn't send a body
  686. inputBuffer.addActiveFilter
  687. (inputFilters[Constants.VOID_FILTER]);
  688. contentDelimitation = true;
  689. }
  690. }
  691. /**
  692. * When committing the response, we have to validate the set of headers, as
  693. * well as setup the response filters.
  694. */
  695. protected void prepareResponse() {
  696. boolean entityBody = true;
  697. contentDelimitation = false;
  698. OutputFilter[] outputFilters = outputBuffer.getFilters();
  699. if (http09 == true) {
  700. // HTTP/0.9
  701. outputBuffer.addActiveFilter
  702. (outputFilters[Constants.IDENTITY_FILTER]);
  703. return;
  704. }
  705. int statusCode = response.getStatus();
  706. if ((statusCode == 204) || (statusCode == 205)
  707. || (statusCode == 304)) {
  708. // No entity body
  709. outputBuffer.addActiveFilter
  710. (outputFilters[Constants.VOID_FILTER]);
  711. entityBody = false;
  712. contentDelimitation = true;
  713. }
  714. MessageBytes methodMB = request.method();
  715. if (methodMB.equals("HEAD")) {
  716. // No entity body
  717. outputBuffer.addActiveFilter
  718. (outputFilters[Constants.VOID_FILTER]);
  719. contentDelimitation = true;
  720. }
  721. // Check for compression
  722. boolean useCompression = false;
  723. if (entityBody && (compressionLevel > 0)) {
  724. useCompression = isCompressable();
  725. // Change content-length to -1 to force chunking
  726. if (useCompression) {
  727. response.setContentLength(-1);
  728. }
  729. }
  730. MimeHeaders headers = response.getMimeHeaders();
  731. if (!entityBody) {
  732. response.setContentLength(-1);
  733. } else {
  734. String contentType = response.getContentType();
  735. if (contentType != null) {
  736. headers.setValue("Content-Type").setString(contentType);
  737. }
  738. String contentLanguage = response.getContentLanguage();
  739. if (contentLanguage != null) {
  740. headers.setValue("Content-Language")
  741. .setString(contentLanguage);
  742. }
  743. }
  744. long contentLength = response.getContentLengthLong();
  745. if (contentLength != -1) {
  746. headers.setValue("Content-Length").setLong(contentLength);
  747. outputBuffer.addActiveFilter
  748. (outputFilters[Constants.IDENTITY_FILTER]);
  749. contentDelimitation = true;
  750. } else {
  751. if (entityBody && http11) {
  752. outputBuffer.addActiveFilter
  753. (outputFilters[Constants.CHUNKED_FILTER]);
  754. contentDelimitation = true;
  755. headers.addValue(Constants.TRANSFERENCODING).setString(Constants.CHUNKED);
  756. } else {
  757. outputBuffer.addActiveFilter
  758. (outputFilters[Constants.IDENTITY_FILTER]);
  759. }
  760. }
  761. if (useCompression) {
  762. outputBuffer.addActiveFilter(outputFilters[Constants.GZIP_FILTER]);
  763. headers.setValue("Content-Encoding").setString("gzip");
  764. // Make Proxies happy via Vary (from mod_deflate)
  765. MessageBytes vary = headers.getValue("Vary");
  766. if (vary == null) {
  767. // Add a new Vary header
  768. headers.setValue("Vary").setString("Accept-Encoding");
  769. } else if (vary.equals("*")) {
  770. // No action required
  771. } else {
  772. // Merge into current header
  773. headers.setValue("Vary").setString(
  774. vary.getString() + ",Accept-Encoding");
  775. }
  776. }
  777. // Add date header
  778. headers.setValue("Date").setString(FastHttpDateFormat.getCurrentDate());
  779. // FIXME: Add transfer encoding header
  780. if ((entityBody) && (!contentDelimitation)) {
  781. // Mark as close the connection after the request, and add the
  782. // connection: close header
  783. keepAlive = false;
  784. }
  785. // If we know that the request is bad this early, add the
  786. // Connection: close header.
  787. keepAlive = keepAlive && !statusDropsConnection(statusCode);
  788. if (!keepAlive) {
  789. headers.addValue(Constants.CONNECTION).setString(Constants.CLOSE);
  790. } else if (!http11 && !error) {
  791. headers.addValue(Constants.CONNECTION).setString(Constants.KEEPALIVE);
  792. }
  793. // Build the response header
  794. outputBuffer.sendStatus();
  795. // Add server header
  796. if (server != null) {
  797. // Always overrides anything the app might set
  798. headers.setValue("Server").setString(server);
  799. } else if (headers.getValue("Server") == null) {
  800. // If app didn't set the header, use the default
  801. outputBuffer.write(Constants.SERVER_BYTES);
  802. }
  803. int size = headers.size();
  804. for (int i = 0; i < size; i++) {
  805. outputBuffer.sendHeader(headers.getName(i), headers.getValue(i));
  806. }
  807. outputBuffer.endHeaders();
  808. }
  809. /**
  810. * Parse host.
  811. */
  812. protected void parseHost(MessageBytes valueMB) {
  813. if (valueMB == null || valueMB.isNull()) {
  814. // HTTP/1.0
  815. // Default is what the socket tells us. Overridden if a host is
  816. // found/parsed
  817. request.setServerPort(socket.getSocket().getLocalPort());
  818. InetAddress localAddress = socket.getSocket().getLocalAddress();
  819. // Setting the socket-related fields. The adapter doesn't know
  820. // about socket.
  821. request.serverName().setString(localAddress.getHostName());
  822. return;
  823. }
  824. ByteChunk valueBC = valueMB.getByteChunk();
  825. byte[] valueB = valueBC.getBytes();
  826. int valueL = valueBC.getLength();
  827. int valueS = valueBC.getStart();
  828. int colonPos = -1;
  829. if (hostNameC.length < valueL) {
  830. hostNameC = new char[valueL];
  831. }
  832. boolean ipv6 = (valueB[valueS] == '[');
  833. boolean bracketClosed = false;
  834. for (int i = 0; i < valueL; i++) {
  835. char b = (char) valueB[i + valueS];
  836. hostNameC[i] = b;
  837. if (b == ']') {
  838. bracketClosed = true;
  839. } else if (b == ':') {
  840. if (!ipv6 || bracketClosed) {
  841. colonPos = i;
  842. break;
  843. }
  844. }
  845. }
  846. if (colonPos < 0) {
  847. if (sslSupport == null) {
  848. // 80 - Default HTTP port
  849. request.setServerPort(80);
  850. } else {
  851. // 443 - Default HTTPS port
  852. request.setServerPort(443);
  853. }
  854. request.serverName().setChars(hostNameC, 0, valueL);
  855. } else {
  856. request.serverName().setChars(hostNameC, 0, colonPos);
  857. int port = 0;
  858. int mult = 1;
  859. for (int i = valueL - 1; i > colonPos; i--) {
  860. int charValue = HexUtils.getDec(valueB[i + valueS]);
  861. if (charValue == -1) {
  862. // Invalid character
  863. error = true;
  864. // 400 - Bad request
  865. response.setStatus(400);
  866. adapter.log(request, response, 0);
  867. break;
  868. }
  869. port = port + (charValue * mult);
  870. mult = 10 * mult;
  871. }
  872. request.setServerPort(port);
  873. }
  874. }
  875. @Override
  876. protected AbstractInputBuffer getInputBuffer() {
  877. return inputBuffer;
  878. }
  879. @Override
  880. protected AbstractOutputBuffer getOutputBuffer() {
  881. return outputBuffer;
  882. }
  883. /**
  884. * Set the socket buffer flag.
  885. */
  886. @Override
  887. public void setSocketBuffer(int socketBuffer) {
  888. super.setSocketBuffer(socketBuffer);
  889. outputBuffer.setSocketBuffer(socketBuffer);
  890. }
  891. }