00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef _PASSENGER_DIRECTORY_MAPPER_H_
00021 #define _PASSENGER_DIRECTORY_MAPPER_H_
00022
00023 #include <string>
00024 #include <set>
00025 #include <cstring>
00026
00027 #include <oxt/backtrace.hpp>
00028
00029 #include "CachedFileStat.h"
00030 #include "Configuration.h"
00031 #include "Utils.h"
00032
00033
00034
00035 #include <httpd.h>
00036 #include <http_core.h>
00037
00038 namespace Passenger {
00039
00040 using namespace std;
00041 using namespace oxt;
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052 class DirectoryMapper {
00053 public:
00054 enum ApplicationType {
00055 NONE,
00056 RAILS,
00057 RACK,
00058 WSGI
00059 };
00060
00061 private:
00062 DirConfig *config;
00063 request_rec *r;
00064 CachedMultiFileStat *mstat;
00065 unsigned int throttleRate;
00066 bool baseURIKnown;
00067 const char *baseURI;
00068 ApplicationType appType;
00069
00070 inline bool shouldAutoDetectRails() {
00071 return config->autoDetectRails == DirConfig::ENABLED ||
00072 config->autoDetectRails == DirConfig::UNSET;
00073 }
00074
00075 inline bool shouldAutoDetectRack() {
00076 return config->autoDetectRack == DirConfig::ENABLED ||
00077 config->autoDetectRack == DirConfig::UNSET;
00078 }
00079
00080 inline bool shouldAutoDetectWSGI() {
00081 return config->autoDetectWSGI == DirConfig::ENABLED ||
00082 config->autoDetectWSGI == DirConfig::UNSET;
00083 }
00084
00085 public:
00086
00087
00088
00089
00090
00091
00092
00093
00094 DirectoryMapper(request_rec *r, DirConfig *config,
00095 CachedMultiFileStat *mstat, unsigned int throttleRate) {
00096 this->r = r;
00097 this->config = config;
00098 this->mstat = mstat;
00099 this->throttleRate = throttleRate;
00100 appType = NONE;
00101 baseURIKnown = false;
00102 baseURI = NULL;
00103 }
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122 const char *getBaseURI() {
00123 TRACE_POINT();
00124 if (baseURIKnown) {
00125 return baseURI;
00126 }
00127
00128 set<string>::const_iterator it;
00129 const char *uri = r->uri;
00130 size_t uri_len = strlen(uri);
00131
00132 if (uri_len == 0 || uri[0] != '/') {
00133 baseURIKnown = true;
00134 return NULL;
00135 }
00136
00137 UPDATE_TRACE_POINT();
00138 for (it = config->railsBaseURIs.begin(); it != config->railsBaseURIs.end(); it++) {
00139 const string &base(*it);
00140 if ( base == "/"
00141 || ( uri_len == base.size() && memcmp(uri, base.c_str(), uri_len) == 0 )
00142 || ( uri_len > base.size() && memcmp(uri, base.c_str(), base.size()) == 0
00143 && uri[base.size()] == '/' )
00144 ) {
00145 baseURIKnown = true;
00146 baseURI = base.c_str();
00147 appType = RAILS;
00148 return baseURI;
00149 }
00150 }
00151
00152 UPDATE_TRACE_POINT();
00153 for (it = config->rackBaseURIs.begin(); it != config->rackBaseURIs.end(); it++) {
00154 const string &base(*it);
00155 if ( base == "/"
00156 || ( uri_len == base.size() && memcmp(uri, base.c_str(), uri_len) == 0 )
00157 || ( uri_len > base.size() && memcmp(uri, base.c_str(), base.size()) == 0
00158 && uri[base.size()] == '/' )
00159 ) {
00160 baseURIKnown = true;
00161 baseURI = base.c_str();
00162 appType = RACK;
00163 return baseURI;
00164 }
00165 }
00166
00167 UPDATE_TRACE_POINT();
00168 if (shouldAutoDetectRails()
00169 && verifyRailsDir(config->getAppRoot(ap_document_root(r)), mstat, throttleRate)) {
00170 baseURIKnown = true;
00171 baseURI = "/";
00172 appType = RAILS;
00173 return baseURI;
00174 }
00175
00176 UPDATE_TRACE_POINT();
00177 if (shouldAutoDetectRack()
00178 && verifyRackDir(config->getAppRoot(ap_document_root(r)), mstat, throttleRate)) {
00179 baseURIKnown = true;
00180 baseURI = "/";
00181 appType = RACK;
00182 return baseURI;
00183 }
00184
00185 UPDATE_TRACE_POINT();
00186 if (shouldAutoDetectWSGI()
00187 && verifyWSGIDir(config->getAppRoot(ap_document_root(r)), mstat, throttleRate)) {
00188 baseURIKnown = true;
00189 baseURI = "/";
00190 appType = WSGI;
00191 return baseURI;
00192 }
00193
00194 baseURIKnown = true;
00195 return NULL;
00196 }
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207 string getPublicDirectory() {
00208 if (!baseURIKnown) {
00209 getBaseURI();
00210 }
00211 if (baseURI == NULL) {
00212 return "";
00213 }
00214
00215 const char *docRoot = ap_document_root(r);
00216 size_t len = strlen(docRoot);
00217 if (len > 0) {
00218 string path;
00219 if (docRoot[len - 1] == '/') {
00220 path.assign(docRoot, len - 1);
00221 } else {
00222 path.assign(docRoot, len);
00223 }
00224 if (strcmp(baseURI, "/") != 0) {
00225 path.append(baseURI);
00226 }
00227 return path;
00228 } else {
00229 return "";
00230 }
00231 }
00232
00233
00234
00235
00236
00237
00238 ApplicationType getApplicationType() {
00239 if (!baseURIKnown) {
00240 getBaseURI();
00241 }
00242 return appType;
00243 }
00244
00245
00246
00247
00248
00249
00250
00251 const char *getApplicationTypeString() {
00252 if (!baseURIKnown) {
00253 getBaseURI();
00254 }
00255 switch (appType) {
00256 case RAILS:
00257 return "rails";
00258 case RACK:
00259 return "rack";
00260 case WSGI:
00261 return "wsgi";
00262 default:
00263 return NULL;
00264 };
00265 }
00266
00267
00268
00269
00270
00271
00272 const char *getEnvironment() {
00273 switch (getApplicationType()) {
00274 case RAILS:
00275 return config->getRailsEnv();
00276 case RACK:
00277 return config->getRackEnv();
00278 default:
00279 return "production";
00280 }
00281 }
00282 };
00283
00284 }
00285
00286 #endif
00287