/* Path is the path to the esp.json */ static int defineApp(HttpRoute *route, cchar *path) { EspRoute *eroute; if ((eroute = espRoute(route)) == 0) { return MPR_ERR_MEMORY; } eroute->top = eroute; if (path) { if (!mprPathExists(path, R_OK)) { mprLog("error esp", 0, "Cannot open %s", path); return MPR_ERR_CANT_FIND; } httpSetRouteHome(route, mprGetPathDir(path)); eroute->configFile = sclone(path); } espSetDefaultDirs(route); httpAddRouteHandler(route, "espHandler", ""); httpAddRouteIndex(route, "index.esp"); httpAddRouteIndex(route, "index.html"); httpSetRouteXsrf(route, 1); mprLog("info esp", 3, "ESP app: %s", path); return 0; }
/* Add cache configuration to the route. This can be called multiple times. Uris, extensions and methods may optionally provide a space or comma separated list of items. If URI is NULL or "*", cache all URIs for this route. Otherwise, cache only the given URIs. The URIs may contain an ordered set of request parameters. For example: "/user/show?name=john&posts=true" Note: the URI should not include the route prefix (scriptName) The extensions should not contain ".". The methods may contain "*" for all methods. */ void httpAddCache(HttpRoute *route, cchar *methods, cchar *uris, cchar *extensions, cchar *types, MprTime clientLifespan, MprTime serverLifespan, int flags) { HttpCache *cache; char *item, *tok; cache = 0; if (!route->caching) { httpAddRouteHandler(route, "cacheHandler", ""); httpAddRouteFilter(route, "cacheFilter", "", HTTP_STAGE_TX); route->caching = mprCreateList(0, 0); } else if (flags & HTTP_CACHE_RESET) { route->caching = mprCreateList(0, 0); } else if (route->parent && route->caching == route->parent->caching) { route->caching = mprCloneList(route->parent->caching); } if ((cache = mprAllocObj(HttpCache, manageHttpCache)) == 0) { return; } if (extensions) { cache->extensions = mprCreateHash(0, 0); for (item = stok(sclone(extensions), " \t,", &tok); item; item = stok(0, " \t,", &tok)) { if (smatch(item, "*")) { extensions = 0; } else { mprAddKey(cache->extensions, item, cache); } } } else if (types) { cache->types = mprCreateHash(0, 0); for (item = stok(sclone(types), " \t,", &tok); item; item = stok(0, " \t,", &tok)) { if (smatch(item, "*")) { extensions = 0; } else { mprAddKey(cache->types, item, cache); } } } if (methods) { cache->methods = mprCreateHash(0, MPR_HASH_CASELESS); for (item = stok(sclone(methods), " \t,", &tok); item; item = stok(0, " \t,", &tok)) { if (smatch(item, "*")) { methods = 0; } else { mprAddKey(cache->methods, item, cache); } } } if (uris) { cache->uris = mprCreateHash(0, 0); for (item = stok(sclone(uris), " \t,", &tok); item; item = stok(0, " \t,", &tok)) { if (flags & HTTP_CACHE_ONLY && route->prefix && !scontains(item, sfmt("prefix=%s", route->prefix))) { /* Auto-add ?prefix=ROUTE_NAME if there is no query */ if (!schr(item, '?')) { item = sfmt("%s?prefix=%s", item, route->prefix); } } mprAddKey(cache->uris, item, cache); } } if (clientLifespan <= 0) { clientLifespan = route->lifespan; } cache->clientLifespan = clientLifespan; if (serverLifespan <= 0) { serverLifespan = route->lifespan; } cache->serverLifespan = serverLifespan; cache->flags = flags; mprAddItem(route->caching, cache); #if UNUSED && KEEP mprLog(3, "Caching route %s for methods %s, URIs %s, extensions %s, types %s, client lifespan %d, server lifespan %d", route->name, (methods) ? methods: "*", (uris) ? uris: "*", (extensions) ? extensions: "*", (types) ? types: "*", cache->clientLifespan / MPR_TICKS_PER_SEC); cache->serverLifespan / MPR_TICKS_PER_SEC); #endif }
/* Configure the server. If the configFile is defined, use it. If not, then consider home, documents, ip and port. */ int maConfigureServer(MaServer *server, cchar *configFile, cchar *home, cchar *documents, cchar *ip, int port) { MaAppweb *appweb; Http *http; HttpEndpoint *endpoint; HttpHost *host; HttpRoute *route; char *path; appweb = server->appweb; http = appweb->http; if (configFile) { path = mprGetAbsPath(configFile); if (maParseConfig(server, path, 0) < 0) { /* mprUserError("Can't configure server using %s", path); */ return MPR_ERR_CANT_INITIALIZE; } return 0; } else { mprLog(2, "DocumentRoot %s", documents); if ((endpoint = httpCreateConfiguredEndpoint(home, documents, ip, port)) == 0) { return MPR_ERR_CANT_OPEN; } maAddEndpoint(server, endpoint); host = mprGetFirstItem(endpoint->hosts); mprAssert(host); route = mprGetFirstItem(host->routes); mprAssert(route); #if UNUSED searchPath = getSearchPath(dir); mprSetModuleSearchPath(searchPath); #endif #if BLD_FEATURE_CGI maLoadModule(appweb, "cgiHandler", "mod_cgi"); if (httpLookupStage(http, "cgiHandler")) { httpAddRouteHandler(route, "cgiHandler", "cgi cgi-nph bat cmd pl py"); /* Add cgi-bin with a route for the /cgi-bin URL prefix. */ path = "cgi-bin"; if (mprPathExists(path, X_OK)) { HttpRoute *cgiRoute; cgiRoute = httpCreateAliasRoute(route, "/cgi-bin/", path, 0); mprLog(4, "ScriptAlias \"/cgi-bin/\":\"%s\"", path); httpSetRouteHandler(cgiRoute, "cgiHandler"); httpFinalizeRoute(cgiRoute); } } #endif #if BLD_FEATURE_ESP maLoadModule(appweb, "espHandler", "mod_esp"); if (httpLookupStage(http, "espHandler")) { httpAddRouteHandler(route, "espHandler", "esp"); } #endif #if BLD_FEATURE_EJSCRIPT maLoadModule(appweb, "ejsHandler", "mod_ejs"); if (httpLookupStage(http, "ejsHandler")) { httpAddRouteHandler(route, "ejsHandler", "ejs"); } #endif #if BLD_FEATURE_PHP maLoadModule(appweb, "phpHandler", "mod_php"); if (httpLookupStage(http, "phpHandler")) { httpAddRouteHandler(route, "phpHandler", "php"); } #endif httpAddRouteHandler(route, "fileHandler", ""); httpFinalizeRoute(route); } if (home) { maSetServerHome(server, home); } if (ip || port > 0) { maSetServerAddress(server, ip, port); } return 0; }
/* function listen(endpoint): Void An endpoint can be either a "port" or "ip:port", or null. If hosted, this call does little -- just add to the ejs->httpServers list. */ static EjsVoid *hs_listen(Ejs *ejs, EjsHttpServer *sp, int argc, EjsObj **argv) { HttpEndpoint *endpoint; HttpHost *host; HttpRoute *route; EjsString *address; EjsObj *loc; EjsPath *documents; if (!sp->hosted) { loc = (argc >= 1) ? argv[0] : ESV(null); if (loc != ESV(null)) { address = ejsToString(ejs, loc); // TODO should permit https://IP:PORT mprParseSocketAddress(address->value, &sp->ip, &sp->port, NULL, 0); } else { address = 0; } if (address == 0) { ejsThrowArgError(ejs, "Missing listen endpoint"); return 0; } if (sp->endpoint) { httpDestroyEndpoint(sp->endpoint); sp->endpoint = 0; } /* The endpoint uses the ejsDispatcher. This is VERY important. All connections will inherit this also. This serializes all activity on one dispatcher. */ if ((endpoint = httpCreateEndpoint(sp->ip, sp->port, ejs->dispatcher)) == 0) { ejsThrowIOError(ejs, "Cannot create Http endpoint object"); return 0; } sp->endpoint = endpoint; host = httpCreateHost(NULL); httpSetHostName(host, sfmt("%s:%d", sp->ip, sp->port)); route = httpCreateConfiguredRoute(host, 1); httpAddRouteMethods(route, "DELETE, HEAD, OPTIONS, PUT"); httpAddRouteHandler(route, "ejsHandler", ""); httpSetRouteTarget(route, "run", 0); httpFinalizeRoute(route); httpSetHostDefaultRoute(host, route); httpAddHostToEndpoint(endpoint, host); if (sp->limits) { ejsSetHttpLimits(ejs, endpoint->limits, sp->limits, 1); } if (sp->incomingStages || sp->outgoingStages || sp->connector) { setHttpPipeline(ejs, sp); } if (sp->ssl) { httpSecureEndpoint(endpoint, sp->ssl); } if (sp->name) { httpSetHostName(host, sp->name); } httpSetSoftware(EJS_HTTPSERVER_NAME); httpSetEndpointAsync(endpoint, sp->async); httpSetEndpointContext(endpoint, sp); httpSetEndpointNotifier(endpoint, stateChangeNotifier); /* This is only required when http is using non-ejs handlers and/or filters */ documents = ejsGetProperty(ejs, sp, ES_ejs_web_HttpServer_documents); if (ejsIs(ejs, documents, Path)) { httpSetRouteDocuments(route, documents->value); } #if KEEP // TODO -- what to do with home? // TODO - if removed, then the "home" property should be removed? home = ejsGetProperty(ejs, sp, ES_ejs_web_HttpServer_home); if (ejsIs(ejs, home, Path)) { httpSetRoutDir(host, home->value); } #endif if (httpStartEndpoint(endpoint) < 0) { httpDestroyEndpoint(sp->endpoint); sp->endpoint = 0; ejsThrowIOError(ejs, "Cannot listen on %s", address->value); } } if (ejs->httpServers == 0) { ejs->httpServers = mprCreateList(-1, MPR_LIST_STATIC_VALUES); } /* Remove to make sure old listening() registrations are removed */ mprRemoveItem(ejs->httpServers, sp); mprAddItem(ejs->httpServers, sp); return 0; }