already_AddRefed<Promise> Cache::Add(JSContext* aContext, const RequestOrUSVString& aRequest, CallerType aCallerType, ErrorResult& aRv) { if (NS_WARN_IF(!mActor)) { aRv.Throw(NS_ERROR_UNEXPECTED); return nullptr; } CacheChild::AutoLock actorLock(mActor); if (!IsValidPutRequestMethod(aRequest, aRv)) { return nullptr; } GlobalObject global(aContext, mGlobal->GetGlobalJSObject()); MOZ_DIAGNOSTIC_ASSERT(!global.Failed()); nsTArray<RefPtr<Request>> requestList(1); RefPtr<Request> request = Request::Constructor(global, aRequest, RequestInit(), aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } nsAutoString url; request->GetUrl(url); if (NS_WARN_IF(!IsValidPutRequestURL(url, aRv))) { return nullptr; } requestList.AppendElement(std::move(request)); return AddAll(global, std::move(requestList), aCallerType, aRv); }
static void processDataFromClient(TConn * const connectionP, abyss_bool const lastReqOnConn, abyss_bool * const keepAliveP) { TSession session; RequestInit(&session, connectionP); session.serverDeniesKeepalive = lastReqOnConn; RequestRead(&session); if (session.status == 0) { if (session.version.major >= 2) ResponseStatus(&session, 505); else if (!RequestValidURI(&session)) ResponseStatus(&session, 400); else runUserHandler(&session, connectionP->server->srvP); } assert(session.status != 0); if (session.responseStarted) HTTPWriteEndChunk(&session); else ResponseError(&session); *keepAliveP = HTTPKeepalive(&session); SessionLog(&session); RequestFree(&session); }
already_AddRefed<Promise> Cache::AddAll(const GlobalObject& aGlobal, nsTArray<RefPtr<Request>>&& aRequestList, CallerType aCallerType, ErrorResult& aRv) { MOZ_DIAGNOSTIC_ASSERT(mActor); // If there is no work to do, then resolve immediately if (aRequestList.IsEmpty()) { RefPtr<Promise> promise = Promise::Create(mGlobal, aRv); if (NS_WARN_IF(!promise)) { return nullptr; } promise->MaybeResolveWithUndefined(); return promise.forget(); } AutoTArray<RefPtr<Promise>, 256> fetchList; fetchList.SetCapacity(aRequestList.Length()); // Begin fetching each request in parallel. For now, if an error occurs just // abandon our previous fetch calls. In theory we could cancel them in the // future once fetch supports it. for (uint32_t i = 0; i < aRequestList.Length(); ++i) { RequestOrUSVString requestOrString; requestOrString.SetAsRequest() = aRequestList[i]; RefPtr<Promise> fetch = FetchRequest(mGlobal, requestOrString, RequestInit(), aCallerType, aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } fetchList.AppendElement(std::move(fetch)); } RefPtr<Promise> promise = Promise::Create(mGlobal, aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } RefPtr<FetchHandler> handler = new FetchHandler(mActor->GetWorkerHolder(), this, std::move(aRequestList), promise); RefPtr<Promise> fetchPromise = Promise::All(aGlobal.Context(), fetchList, aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } fetchPromise->AppendNativeHandler(handler); return promise.forget(); }
PassRefPtrWillBeRawPtr<Request> Request::create(ExecutionContext* context, Request* input, const Dictionary& init, ExceptionState& exceptionState) { // "1. Let |request| be |input|'s associated request, if |input| is a // Request object, and a new request otherwise." // "2. Set |request| to a restricted copy of itself." RefPtrWillBeRawPtr<FetchRequestData> request(input->request()->createRestrictedCopy(context, SecurityOrigin::create(context->url()))); // "3. Let |fallbackMode| be null." // "4. Let |fallbackCredentials| be null." // Instead of using null as a special fallback value, just pass the current // mode and credentials; it has the same effect. const FetchRequestData::Mode currentMode = request->mode(); const FetchRequestData::Credentials currentCredentials = request->credentials(); return createRequestWithRequestData(request.release(), RequestInit(init), currentMode, currentCredentials, exceptionState); }
already_AddRefed<Promise> Cache::AddAll(JSContext* aContext, const Sequence<OwningRequestOrUSVString>& aRequestList, CallerType aCallerType, ErrorResult& aRv) { if (NS_WARN_IF(!mActor)) { aRv.Throw(NS_ERROR_UNEXPECTED); return nullptr; } CacheChild::AutoLock actorLock(mActor); GlobalObject global(aContext, mGlobal->GetGlobalJSObject()); MOZ_DIAGNOSTIC_ASSERT(!global.Failed()); nsTArray<RefPtr<Request>> requestList(aRequestList.Length()); for (uint32_t i = 0; i < aRequestList.Length(); ++i) { RequestOrUSVString requestOrString; if (aRequestList[i].IsRequest()) { requestOrString.SetAsRequest() = aRequestList[i].GetAsRequest(); if (NS_WARN_IF(!IsValidPutRequestMethod(requestOrString.GetAsRequest(), aRv))) { return nullptr; } } else { requestOrString.SetAsUSVString().Rebind( aRequestList[i].GetAsUSVString().Data(), aRequestList[i].GetAsUSVString().Length()); } RefPtr<Request> request = Request::Constructor(global, requestOrString, RequestInit(), aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } nsAutoString url; request->GetUrl(url); if (NS_WARN_IF(!IsValidPutRequestURL(url, aRv))) { return nullptr; } requestList.AppendElement(std::move(request)); } return AddAll(global, std::move(requestList), aCallerType, aRv); }
PassRefPtrWillBeRawPtr<Request> Request::create(ExecutionContext* context, const String& input, const Dictionary& init, ExceptionState& exceptionState) { // "1. Let |request| be |input|'s associated request, if |input| is a // Request object, and a new request otherwise." RefPtrWillBeRawPtr<FetchRequestData> request(FetchRequestData::create(context)); // "2. Set |request| to a restricted copy of itself." request = request->createRestrictedCopy(context, SecurityOrigin::create(context->url())); // "5. If |input| is a string, run these substeps:" // "1. Let |parsedURL| be the result of parsing |input| with entry settings // object's API base URL." KURL parsedURL = context->completeURL(input); // "2. If |parsedURL| is failure, throw a TypeError." if (!parsedURL.isValid()) { exceptionState.throwTypeError("Invalid URL"); return nullptr; } // "3. Set |request|'s url to |parsedURL|." request->setURL(parsedURL); // "4. Set |fallbackMode| to CORS." // "5. Set |fallbackCredentials| to omit." return createRequestWithRequestData(request.release(), RequestInit(init), FetchRequestData::CORSMode, FetchRequestData::OmitCredentials, exceptionState); }
static void processRequestFromClient(TConn * const connectionP, bool const lastReqOnConn, uint32_t const timeout, bool * const keepAliveP) { /*---------------------------------------------------------------------------- Get and execute one HTTP request from client connection *connectionP, through the connection buffer. I.e. Some of the request may already be in the connection buffer, and we may leave some of later requests in the connection buffer. In fact, due to timing considerations, we assume the client has begun sending the request, which as a practical matter means Caller has already deposited some of it in the connection buffer. If there isn't one full request in the buffer now, we wait for one full request to come through the buffer, up to 'timeout'. We return as *keepAliveP whether Caller should keep the connection alive for a while for possible future requests from the client, based on 'lastReqOnConn' and the content of the HTTP request. Executing the request consists primarily of calling the URI handlers that are associated with the connection (*connectionP), passing each the request information we read. Each handler can respond according to the HTTP method (GET, POST, etc) and URL etc, and that response may be either to execute the request and send the response or refuse the request and let us call the next one in the list. -----------------------------------------------------------------------------*/ TSession session; const char * error; uint16_t httpErrorCode; RequestInit(&session, connectionP); session.serverDeniesKeepalive = lastReqOnConn; RequestRead(&session, timeout, &error, &httpErrorCode); if (error) { ResponseStatus(&session, httpErrorCode); ResponseError2(&session, error); xmlrpc_strfree(error); } else { if (session.version.major >= 2) handleReqTooNewHttpVersion(&session); else if (!RequestValidURI(&session)) handleReqInvalidURI(&session); else runUserHandler(&session, connectionP->server->srvP); } assert(session.status != 0); if (session.responseStarted) HTTPWriteEndChunk(&session); else ResponseError(&session); *keepAliveP = HTTPKeepalive(&session); SessionLog(&session); RequestFree(&session); }
static void testPathParams(void) { /* A buffer to hold our test paths */ char path[1024]; char *pParam; /* We need a request structure in order to test the path params. In order to create a request structure, we need a connection. We don't use any of the data within the connection structure, so it can just be junk. */ TConn junkConnection; TRequest testRequest; RequestInit(&testRequest, &junkConnection); /* Try some pathological cases just to make sure we don't dump core */ strcpy(path, "/"); ParsePathParams(NULL, NULL); ParsePathParams(NULL, path); ParsePathParams(&testRequest, NULL); /* Though this should never happen, see if we can handle an empty string */ TableReset(&testRequest.path_params); strcpy(path, ""); ParsePathParams(&testRequest, path); assert(*path == '\0'); assert(testRequest.path_params.size == 0); /* Now, try some real paths with no path parameters */ strcpy(path, "/"); ParsePathParams(&testRequest, path); assert(strcmp(path, "/") == 0); assert(testRequest.path_params.size == 0); strcpy(path, "/foo"); ParsePathParams(&testRequest, path); assert(strcmp(path, "/foo") == 0); assert(testRequest.path_params.size == 0); strcpy(path, "/foo/bar"); ParsePathParams(&testRequest, path); assert(strcmp(path, "/foo/bar") == 0); assert(testRequest.path_params.size == 0); strcpy(path, "/foo/bar/"); ParsePathParams(&testRequest, path); assert(strcmp(path, "/foo/bar/") == 0); assert(testRequest.path_params.size == 0); /* Now try some paths with parameters. */ TableReset(&testRequest.path_params); strcpy(path, "/ivr;lc=en-us"); ParsePathParams(&testRequest, path); pParam = RequestPathParam(&testRequest, "/ivr"); assert(pParam != NULL ); assert(strcmp(path, "/ivr") == 0 ); assert(strcmp(pParam, "lc=en-us") == 0 ); assert(testRequest.path_params.size == 1 ); TableReset(&testRequest.path_params); strcpy(path, "/ivr;lc=en-us/main.pg"); ParsePathParams(&testRequest, path); pParam = RequestPathParam(&testRequest, "/ivr"); assert(pParam != NULL ); assert(strcmp(path, "/ivr/main.pg") == 0 ); assert(strcmp(pParam, "lc=en-us") == 0 ); assert(testRequest.path_params.size == 1 ); TableReset(&testRequest.path_params); strcpy(path, "/ivr;lc=en-us;cf=orion/main.pg"); ParsePathParams(&testRequest, path); pParam = RequestPathParam(&testRequest, "/ivr"); assert(strcmp(path, "/ivr/main.pg") == 0 ); assert(strcmp(pParam, "lc=en-us;cf=orion") == 0 ); assert(testRequest.path_params.size == 1 ); TableReset(&testRequest.path_params); strcpy(path, "/ivr;lc=en-us;cf=orion/prompts;type=rapid/main.pg"); ParsePathParams(&testRequest, path); pParam = RequestPathParam(&testRequest, "/ivr"); assert(pParam != NULL ); assert(strcmp(path, "/ivr/prompts/main.pg") == 0 ); assert(strcmp(pParam, "lc=en-us;cf=orion") == 0 ); pParam = RequestPathParam(&testRequest, "/ivr/prompts"); assert(pParam != NULL ); assert(strcmp(pParam, "type=rapid") == 0 ); assert(testRequest.path_params.size == 2 ); /* Now try some odd cases. The URI RFC2396 allows the path parameter to be empty. It also allows path parameters directly after a slash. We can also end a path in path parameters. */ TableReset(&testRequest.path_params); strcpy(path, "/;foo=bar"); ParsePathParams(&testRequest, path); pParam = RequestPathParam(&testRequest, "/"); assert(pParam != NULL ); assert(strcmp(path, "/") == 0 ); assert(strcmp(pParam, "foo=bar") == 0 ); assert(testRequest.path_params.size == 1 ); TableReset(&testRequest.path_params); strcpy(path, "/ivr;"); ParsePathParams(&testRequest, path); pParam = RequestPathParam(&testRequest, "/ivr"); assert(pParam != NULL ); assert(strcmp(path, "/ivr") == 0 ); assert(strcmp(pParam, "") == 0 ); assert(testRequest.path_params.size == 1 ); TableReset(&testRequest.path_params); strcpy(path, "/ivr/main.pg;id=23"); ParsePathParams(&testRequest, path); pParam = RequestPathParam(&testRequest, "/ivr/main.pg"); assert(pParam != NULL ); assert(strcmp(path, "/ivr/main.pg") == 0 ); assert(strcmp(pParam, "id=23") == 0 ); assert(testRequest.path_params.size == 1 ); /* Put an escaped character (try a null just to be really nasty) */ TableReset(&testRequest.path_params); strcpy(path, "/ivr;lc%00en-us/main.pg"); ParsePathParams(&testRequest, path); pParam = RequestPathParam(&testRequest, "/ivr"); assert(pParam != NULL ); assert(strcmp(path, "/ivr/main.pg") == 0 ); assert(strcmp(pParam, "lc%00en-us") == 0 ); assert(testRequest.path_params.size == 1 ); /* Try one with lots of parameters */ TableReset(&testRequest.path_params); strcpy(path, "/a;a/b;b/c;c/d;d/e;e/f;f/;g"); ParsePathParams(&testRequest, path); assert(testRequest.path_params.size == 7 ); assert(strcmp(path, "/a/b/c/d/e/f/") == 0 ); pParam = RequestPathParam(&testRequest, "/a"); assert(pParam != NULL ); assert(strcmp(pParam, "a") == 0 ); pParam = RequestPathParam(&testRequest, "/a/b"); assert(pParam != NULL ); assert(strcmp(pParam, "b") == 0 ); pParam = RequestPathParam(&testRequest, "/a/b/c"); assert(pParam != NULL ); assert(strcmp(pParam, "c") == 0 ); pParam = RequestPathParam(&testRequest, "/a/b/c/d"); assert(pParam != NULL ); assert(strcmp(pParam, "d") == 0 ); pParam = RequestPathParam(&testRequest, "/a/b/c/d/e"); assert(pParam != NULL ); assert(strcmp(pParam, "e") == 0 ); pParam = RequestPathParam(&testRequest, "/a/b/c/d/e/f"); assert(pParam != NULL ); assert(strcmp(pParam, "f") == 0 ); pParam = RequestPathParam(&testRequest, "/a/b/c/d/e/f/"); assert(pParam != NULL ); assert(strcmp(pParam, "g") == 0 ); }
void ServerFunc(TConn *c) { TRequest r; uint32 ka = 0; /* sanity */ if (!c) { return; } ka=c->server->keepalivemaxconn; c->pool = ap_make_sub_pool( c->server->pool ); c->server->stat_conns++; RequestInit(&r,c); /* tell connection handlers - new connection */ ap_conn_init_modules( c ); while (ka--) { c->start_time = ap_time(); /* Wait to read until timeout */ if (!ConnRead(c,c->server->keepalivetimeout)) { break; } /* CODE_PROBE_1("Server - Req Read Start (%x)",c); */ if (RequestRead(&r)) { /* Check if it is the last keepalive */ if (ka==1) { r.keepalive=FALSE; } r.cankeepalive=r.keepalive; if (r.status==0) { if (r.versionmajor>=2) { ResponseStatus(&r,505); } else if (!RequestValidURI(&r)) { ResponseStatus(&r,400); } else { if( ap_invoke_handler( &r ) == DECLINED ) { ((HANDLER)(c->server->defaulthandler))(&r); } } } } /* CODE_PROBE_1("Server - Req Read End (%x)",c); */ HTTPWriteEnd(&r); ConnWriteFlush( c ); if (!r.done) ResponseError(&r); RequestLog(&r); /* do flow stat update */ c->server->stat_inbytes += c->inbytes; c->server->stat_outbytes += c->outbytes; c->server->stat_data_time += ap_time() - c->start_time; if( c->server->stopped ) { break; } if (!(r.keepalive && r.cankeepalive)) { break; } RequestReset(&r,c); ConnReadInit(c); /* CODE_PROBE_1("Server - ConnReadInit - Bottom (%x)",c); */ } /* tell connection handlers session complete */ ap_conn_exit_modules( c ); ap_destroy_pool( c->pool ); RequestFree(&r); SocketClose(&(c->socket)); }
Request* Request::create(ExecutionContext* context, Request* input, const Dictionary& init, ExceptionState& exceptionState) { return createRequestWithRequestOrString(context, input, String(), RequestInit(context, init, exceptionState), exceptionState); }