~alinuxninja/nginx-edge/trunk

« back to all changes in this revision

Viewing changes to debian/modules/ngx_pagespeed/psol/include/net/instaweb/apache/instaweb_handler.h

  • Committer: Vivian
  • Date: 2015-12-04 18:20:11 UTC
  • Revision ID: git-v1:a36f2bc32e884f7473b3a47040e5411306144d7d
* Do not extract psol.tar.gz

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// Copyright 2010 Google Inc.
2
 
//
3
 
// Licensed under the Apache License, Version 2.0 (the "License");
4
 
// you may not use this file except in compliance with the License.
5
 
// You may obtain a copy of the License at
6
 
//
7
 
//      http://www.apache.org/licenses/LICENSE-2.0
8
 
//
9
 
// Unless required by applicable law or agreed to in writing, software
10
 
// distributed under the License is distributed on an "AS IS" BASIS,
11
 
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
 
// See the License for the specific language governing permissions and
13
 
// limitations under the License.
14
 
//
15
 
// Author: lsong@google.com (Libo Song)
16
 
//         jmarantz@google.com (Joshua Marantz)
17
 
//
18
 
// The Apache handler for rewriten resources and a couple other Apache hooks.
19
 
 
20
 
#ifndef NET_INSTAWEB_APACHE_INSTAWEB_HANDLER_H_
21
 
#define NET_INSTAWEB_APACHE_INSTAWEB_HANDLER_H_
22
 
 
23
 
#include "net/instaweb/apache/apache_writer.h"
24
 
#include "net/instaweb/http/public/request_context.h"
25
 
#include "net/instaweb/rewriter/public/rewrite_options.h"
26
 
#include "net/instaweb/rewriter/public/rewrite_query.h"
27
 
#include "pagespeed/apache/apache_fetch.h"
28
 
#include "pagespeed/kernel/base/basictypes.h"
29
 
#include "pagespeed/kernel/base/scoped_ptr.h"
30
 
#include "pagespeed/kernel/base/string.h"
31
 
#include "pagespeed/kernel/base/string_util.h"
32
 
#include "pagespeed/kernel/base/thread_system.h"
33
 
#include "pagespeed/kernel/http/content_type.h"
34
 
#include "pagespeed/kernel/http/google_url.h"
35
 
 
36
 
#include "apr_pools.h"  // for apr_status_t
37
 
// The httpd header must be after the instaweb_context.h. Otherwise,
38
 
// the compiler will complain
39
 
// "strtoul_is_not_a_portable_function_use_strtol_instead".
40
 
#include "httpd.h"
41
 
 
42
 
namespace net_instaweb {
43
 
 
44
 
class ApacheRequestContext;
45
 
class ApacheRewriteDriverFactory;
46
 
class ApacheServerContext;
47
 
class InPlaceResourceRecorder;
48
 
class QueryParams;
49
 
class RequestHeaders;
50
 
class ResponseHeaders;
51
 
class RewriteDriver;
52
 
class ServerContext;
53
 
class SystemRewriteOptions;
54
 
 
55
 
// Context for handling a request, computing options and request headers in
56
 
// the constructor.
57
 
//
58
 
// TODO(jmarantz): There are many static methods in this class.  Some
59
 
// of them need to stay that way as they are used as C entry points.
60
 
// Some are helper methods, and we could adopt a policy of requiring
61
 
// the static methods to instantiate the class (possibly making its
62
 
// constructor lighter weight) and then calling them explicitly.  For
63
 
// the time being, we'll leave these static methods with the
64
 
// non-compliant lower_case_names_with_underscores naming convention
65
 
// and fix their naming when we update whether they should be static
66
 
// or not.
67
 
class InstawebHandler {
68
 
 public:
69
 
  explicit InstawebHandler(request_rec* request);
70
 
  ~InstawebHandler();
71
 
 
72
 
  // Any PageSpeed query params are removed.
73
 
  const GoogleUrl& stripped_gurl() const { return stripped_gurl_; }
74
 
  const RequestContextPtr request_context() const { return request_context_; }
75
 
  bool use_custom_options() const { return custom_options_.get() != NULL; }
76
 
  const QueryParams& query_params() { return rewrite_query_.query_params(); }
77
 
  const QueryParams& pagespeed_query_params() {
78
 
    return rewrite_query_.pagespeed_query_params();
79
 
  }
80
 
  const QueryParams& pagespeed_option_cookies() {
81
 
    return rewrite_query_.pagespeed_option_cookies();
82
 
  }
83
 
 
84
 
  void SetupSpdyConnectionIfNeeded();
85
 
  void RemoveStrippedResponseHeadersFromApacheRequest();
86
 
 
87
 
  // Makes a driver from the request_context and options.  Note that
88
 
  // this can only be called once, as it potentially mutates the options
89
 
  // as it transfers ownership of custom_options.
90
 
  RewriteDriver* MakeDriver();
91
 
 
92
 
  // Allocates a Fetch object associated with the current request and
93
 
  // the specified URL.  Include in debug_info anything that's cheap to create
94
 
  // and would be informative if something went wrong with the fetch.
95
 
  // If any uses will be from other threads you must set buffered=true to keep
96
 
  // your other thread from getting blocked if our output is being read by a
97
 
  // slow reader.
98
 
  ApacheFetch* MakeFetch(
99
 
      const GoogleString& url, bool buffered, StringPiece debug_info);
100
 
 
101
 
  // Allocates a Fetch object associated with the current request and its URL.
102
 
  // Please read the comment above before setting buffered=false.
103
 
  ApacheFetch* MakeFetch(bool buffered, StringPiece debug_info) {
104
 
    return MakeFetch(original_url_, buffered, debug_info);
105
 
  }
106
 
 
107
 
  // Attempts to handle this as a proxied resource (see
108
 
  // MapProxyDomain). Returns false if the proxy handling didn't
109
 
  // occur, and another handler should take over the request.
110
 
  bool HandleAsProxy();
111
 
 
112
 
  // Attempts to handle this as an in-place resource. Returns false if
113
 
  // the in-place handling didn't occur, and another handler should take
114
 
  // over the request.
115
 
  bool HandleAsInPlace();
116
 
 
117
 
  // Unconditionally handles a resource that looks like a .pagespeed. resource,
118
 
  // whether the result is success or failure.
119
 
  void HandleAsPagespeedResource();
120
 
 
121
 
  // Waits for an outstanding fetch (obtained by MakeFetch) to complete or time
122
 
  // out.  Returns true if the fetch completes, false if we time out and abandon
123
 
  // the request.  On failure we haven't sent out headers or any other content,
124
 
  // so it's safe to decline this request and another Apache content handler can
125
 
  // look into it.
126
 
  bool WaitForFetch();
127
 
 
128
 
  RequestHeaders* ReleaseRequestHeaders() { return request_headers_.release(); }
129
 
 
130
 
  // Returns the options, whether they were custom-computed due to htaccess
131
 
  // file, query params, or headers, or were the default options for the vhost.
132
 
  const SystemRewriteOptions* options() { return options_; }
133
 
 
134
 
  // Was this request made by mod_pagespeed itself? If so, we should not try to
135
 
  // handle it, just let Apache deal with it like normal.
136
 
  static bool is_pagespeed_subrequest(request_rec* request);
137
 
 
138
 
  // Handle mod_pagespeed-specific requests. Handles both .pagespeed. rewritten
139
 
  // resources and /mod_pagespeed_statistics, /mod_pagespeed_beacon, etc.
140
 
  static apr_status_t instaweb_handler(request_rec* request);
141
 
 
142
 
  // Save the original URL as a request "note" before mod_rewrite has
143
 
  // a chance to corrupt mod_pagespeed's generated URLs, which would
144
 
  // prevent instaweb_handler from being able to decode the resource.
145
 
  static apr_status_t save_url_hook(request_rec *request);
146
 
 
147
 
  // Implementation of the Apache 'translate_name' hook. Used by the actual hook
148
 
  // 'save_url_hook' and directly when we already have the server context.
149
 
  static apr_status_t save_url_in_note(request_rec *request,
150
 
                                       ApacheServerContext* server_context);
151
 
 
152
 
  // By default, apache imposes limitations on URL segments of around
153
 
  // 256 characters that appear to correspond to filename limitations.
154
 
  // To prevent that, we hook map_to_storage for our own purposes.
155
 
  static apr_status_t instaweb_map_to_storage(request_rec* request);
156
 
 
157
 
  // This must be called on any InPlaceResourceRecorder allocated by
158
 
  // instaweb_handler before calling DoneAndSetHeaders() on it.
159
 
  static void AboutToBeDoneWithRecorder(request_rec* request,
160
 
                                        InPlaceResourceRecorder* recorder);
161
 
 
162
 
 private:
163
 
  // Evaluate custom_options based upon global_options, directory-specific
164
 
  // options and query-param/request-header options. Stores computed options
165
 
  // in custom_options_ if needed.  Sets options_ to point to the correct
166
 
  // options to use.
167
 
  void ComputeCustomOptions();
168
 
 
169
 
  static bool IsCompressibleContentType(const char* content_type);
170
 
 
171
 
  static void send_out_headers_and_body(
172
 
      request_rec* request,
173
 
      const ResponseHeaders& response_headers,
174
 
      const GoogleString& output);
175
 
 
176
 
  // Determines whether the url can be handled as a mod_pagespeed or in-place
177
 
  // optimized resource, and handles it, returning true.  Success status is
178
 
  // written to the status code in the response headers.
179
 
  static bool handle_as_resource(ApacheServerContext* server_context,
180
 
                                 request_rec* request,
181
 
                                 GoogleUrl* gurl);
182
 
 
183
 
  // Write response headers and send out headers and output, including
184
 
  // the option for a custom Content-Type.
185
 
  static void write_handler_response(const StringPiece& output,
186
 
                                     request_rec* request,
187
 
                                     ContentType content_type,
188
 
                                     const StringPiece& cache_control);
189
 
  static void write_handler_response(const StringPiece& output,
190
 
                                     request_rec* request);
191
 
 
192
 
  // Returns request URL if it was a .pagespeed. rewritten resource URL.
193
 
  // Otherwise returns NULL. Since other Apache modules can change request->uri,
194
 
  // we stow the original request URL in a note. This method reads that note
195
 
  // and thus should return the URL that the browser actually requested (rather
196
 
  // than a mod_rewrite altered URL).
197
 
  static const char* get_instaweb_resource_url(
198
 
      request_rec* request, ApacheServerContext* server_context);
199
 
 
200
 
  // Helper function to support the LogRequestHeadersHandler.  Called
201
 
  // once for each header to write header data in a form suitable for
202
 
  // javascript inlining.  Used only for tests.
203
 
  static int log_request_headers(void* logging_data, const char* key,
204
 
                                 const char* value);
205
 
 
206
 
  static void instaweb_static_handler(request_rec* request,
207
 
                                      ApacheServerContext* server_context);
208
 
 
209
 
  static apr_status_t instaweb_statistics_handler(
210
 
      request_rec* request, ApacheServerContext* server_context,
211
 
      ApacheRewriteDriverFactory* factory);
212
 
 
213
 
  // Append the query params from a request into data. This just
214
 
  // parses the query params from a request URL. For parsing the query
215
 
  // params from a POST body, use parse_body_from_post(). Return true
216
 
  // if successful, otherwise, returns false and sets ret to the
217
 
  // appropriate status.
218
 
  static bool parse_query_params(const request_rec* request, GoogleString* data,
219
 
                                 apr_status_t* ret);
220
 
 
221
 
  // Read the body from a POST request and append to data. Return true
222
 
  // if successful, otherwise, returns false and sets ret to the
223
 
  // appropriate status.
224
 
  static bool parse_body_from_post(const request_rec* request,
225
 
                                   GoogleString* data, apr_status_t* ret);
226
 
 
227
 
  static apr_status_t instaweb_beacon_handler(
228
 
      request_rec* request, ApacheServerContext* server_context);
229
 
 
230
 
  static bool IsBeaconUrl(const RewriteOptions::BeaconUrl& beacons,
231
 
                          const GoogleUrl& gurl);
232
 
 
233
 
  request_rec* request_;
234
 
  RequestContextPtr request_context_;
235
 
  ApacheRequestContext* apache_request_context_;  // owned by request_context_.
236
 
  ApacheServerContext* server_context_;
237
 
  scoped_ptr<RequestHeaders> request_headers_;
238
 
  scoped_ptr<ResponseHeaders> response_headers_;
239
 
  GoogleString original_url_;
240
 
  GoogleUrl stripped_gurl_;  // Any PageSpeed query params are removed.
241
 
  scoped_ptr<SystemRewriteOptions> custom_options_;
242
 
 
243
 
  // These options_ can be in one of three states:
244
 
  //   - they can point to the config's global_options
245
 
  //   - they can point to the custom_options_
246
 
  //   - after driver creation, they can point to the rewrite_driver_->options()
247
 
  // Thus this set of options is not owned by this class.
248
 
  //
249
 
  // In all three of these states, the pointer and semantics will always be
250
 
  // the same.  Only the ownership changes.
251
 
  const SystemRewriteOptions* options_;
252
 
  RewriteDriver* rewrite_driver_;
253
 
  int num_response_attributes_;
254
 
  RewriteQuery rewrite_query_;
255
 
  ApacheFetch* fetch_;
256
 
 
257
 
  DISALLOW_COPY_AND_ASSIGN(InstawebHandler);
258
 
};
259
 
 
260
 
}  // namespace net_instaweb
261
 
 
262
 
#endif  // NET_INSTAWEB_APACHE_INSTAWEB_HANDLER_H_