View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
16  //  ========================================================================
17  //
18  
19  package org.eclipse.jetty.fcgi.client.http;
20  
21  import java.net.URI;
22  import java.util.Locale;
23  
24  import org.eclipse.jetty.client.HttpChannel;
25  import org.eclipse.jetty.client.HttpContent;
26  import org.eclipse.jetty.client.HttpExchange;
27  import org.eclipse.jetty.client.HttpSender;
28  import org.eclipse.jetty.client.api.Request;
29  import org.eclipse.jetty.fcgi.FCGI;
30  import org.eclipse.jetty.fcgi.generator.ClientGenerator;
31  import org.eclipse.jetty.fcgi.generator.Generator;
32  import org.eclipse.jetty.http.HttpField;
33  import org.eclipse.jetty.http.HttpFields;
34  import org.eclipse.jetty.http.HttpHeader;
35  import org.eclipse.jetty.util.BufferUtil;
36  import org.eclipse.jetty.util.Callback;
37  import org.eclipse.jetty.util.Jetty;
38  
39  public class HttpSenderOverFCGI extends HttpSender
40  {
41      private final ClientGenerator generator;
42  
43      public HttpSenderOverFCGI(HttpChannel channel)
44      {
45          super(channel);
46          this.generator = new ClientGenerator(channel.getHttpDestination().getHttpClient().getByteBufferPool());
47      }
48  
49      @Override
50      protected HttpChannelOverFCGI getHttpChannel()
51      {
52          return (HttpChannelOverFCGI)super.getHttpChannel();
53      }
54  
55      @Override
56      protected void sendHeaders(HttpExchange exchange, HttpContent content, Callback callback)
57      {
58          Request request = exchange.getRequest();
59          // Copy the request headers to be able to convert them properly
60          HttpFields headers = new HttpFields();
61          for (HttpField field : request.getHeaders())
62              headers.put(field);
63          HttpFields fcgiHeaders = new HttpFields();
64  
65          // FastCGI headers based on the URI
66          URI uri = request.getURI();
67          String path = uri.getRawPath();
68          fcgiHeaders.put(FCGI.Headers.DOCUMENT_URI, path);
69          String query = uri.getRawQuery();
70          fcgiHeaders.put(FCGI.Headers.QUERY_STRING, query == null ? "" : query);
71  
72          // FastCGI headers based on HTTP headers
73          HttpField httpField = headers.remove(HttpHeader.AUTHORIZATION);
74          if (httpField != null)
75              fcgiHeaders.put(FCGI.Headers.AUTH_TYPE, httpField.getValue());
76          httpField = headers.remove(HttpHeader.CONTENT_LENGTH);
77          fcgiHeaders.put(FCGI.Headers.CONTENT_LENGTH, httpField == null ? "" : httpField.getValue());
78          httpField = headers.remove(HttpHeader.CONTENT_TYPE);
79          fcgiHeaders.put(FCGI.Headers.CONTENT_TYPE, httpField == null ? "" : httpField.getValue());
80  
81          // FastCGI headers that are not based on HTTP headers nor URI
82          fcgiHeaders.put(FCGI.Headers.REQUEST_METHOD, request.getMethod());
83          fcgiHeaders.put(FCGI.Headers.SERVER_PROTOCOL, request.getVersion().asString());
84          fcgiHeaders.put(FCGI.Headers.GATEWAY_INTERFACE, "CGI/1.1");
85          fcgiHeaders.put(FCGI.Headers.SERVER_SOFTWARE, "Jetty/" + Jetty.VERSION);
86  
87          // Translate remaining HTTP header into the HTTP_* format
88          for (HttpField field : headers)
89          {
90              String name = field.getName();
91              String fcgiName = "HTTP_" + name.replaceAll("-", "_").toUpperCase(Locale.ENGLISH);
92              fcgiHeaders.add(fcgiName, field.getValue());
93          }
94  
95          // Give a chance to the transport implementation to customize the FastCGI headers
96          HttpClientTransportOverFCGI transport = (HttpClientTransportOverFCGI)getHttpChannel().getHttpDestination().getHttpClient().getTransport();
97          transport.customize(request, fcgiHeaders);
98  
99          int id = getHttpChannel().getRequest();
100         boolean hasContent = content.hasContent();
101         Generator.Result headersResult = generator.generateRequestHeaders(id, fcgiHeaders,
102                 hasContent ? callback : Callback.NOOP);
103         if (hasContent)
104         {
105             getHttpChannel().flush(headersResult);
106         }
107         else
108         {
109             Generator.Result noContentResult = generator.generateRequestContent(id, BufferUtil.EMPTY_BUFFER, true, callback);
110             getHttpChannel().flush(headersResult, noContentResult);
111         }
112     }
113 
114     @Override
115     protected void sendContent(HttpExchange exchange, HttpContent content, Callback callback)
116     {
117         if (content.isConsumed())
118         {
119             callback.succeeded();
120         }
121         else
122         {
123             int request = getHttpChannel().getRequest();
124             Generator.Result result = generator.generateRequestContent(request, content.getByteBuffer(), content.isLast(), callback);
125             getHttpChannel().flush(result);
126         }
127     }
128 }