void FetchResponse::initializeWith(const Dictionary& init, ExceptionCode& ec) { int status; if (!init.get("status", status)) { ec = TypeError; return; } if (status < 200 || status > 599) { ec = RangeError; return; } // FIXME: Validate reason phrase (https://tools.ietf.org/html/rfc7230#section-3.1.2). String statusText; if (!init.get("statusText", statusText)) { ec = TypeError; return; } m_response.setHTTPStatusCode(status); m_response.setHTTPStatusText(statusText); RefPtr<FetchHeaders> initialHeaders; if (init.get("headers", initialHeaders)) m_headers->fill(initialHeaders.get()); JSC::JSValue body; if (init.get("body", body)) { if (isNullBodyStatus(status)) { ec = TypeError; return; } m_body = FetchBody::extract(*init.execState(), body); if (m_headers->fastGet(HTTPHeaderName::ContentType).isEmpty() && !m_body.mimeType().isEmpty()) m_headers->fastSet(HTTPHeaderName::ContentType, m_body.mimeType()); } }
Response* Response::create(ExecutionContext* context, PassOwnPtr<FetchDataConsumerHandle> bodyHandle, const String& contentType, const ResponseInit& init, ExceptionState& exceptionState) { unsigned short status = init.status; // "1. If |init|'s status member is not in the range 200 to 599, inclusive, throw a // RangeError." if (status < 200 || 599 < status) { exceptionState.throwRangeError(ExceptionMessages::indexOutsideRange<unsigned>("status", status, 200, ExceptionMessages::InclusiveBound, 599, ExceptionMessages::InclusiveBound)); return nullptr; } // "2. If |init|'s statusText member does not match the Reason-Phrase // token production, throw a TypeError." if (!isValidReasonPhrase(init.statusText)) { exceptionState.throwTypeError("Invalid statusText"); return nullptr; } // "3. Let |r| be a new Response object, associated with a new response, // Headers object, and Body object." Response* r = new Response(context); // "4. Set |r|'s response's status to |init|'s status member." r->m_response->setStatus(init.status); // "5. Set |r|'s response's status message to |init|'s statusText member." r->m_response->setStatusMessage(AtomicString(init.statusText)); // "6. If |init|'s headers member is present, run these substeps:" if (init.headers) { // "1. Empty |r|'s response's header list." r->m_response->headerList()->clearList(); // "2. Fill |r|'s Headers object with |init|'s headers member. Rethrow // any exceptions." r->m_headers->fillWith(init.headers.get(), exceptionState); if (exceptionState.hadException()) return nullptr; } else if (!init.headersDictionary.isUndefinedOrNull()) { // "1. Empty |r|'s response's header list." r->m_response->headerList()->clearList(); // "2. Fill |r|'s Headers object with |init|'s headers member. Rethrow // any exceptions." r->m_headers->fillWith(init.headersDictionary, exceptionState); if (exceptionState.hadException()) return nullptr; } // "7. If body is given, run these substeps:" if (bodyHandle) { // "1. If |init|'s status member is a null body status, throw a // TypeError." // "2. Let |stream| and |Content-Type| be the result of extracting // body." // "3. Set |r|'s response's body to |stream|." // "4. If |Content-Type| is non-null and |r|'s response's header list // contains no header named `Content-Type`, append `Content-Type`/ // |Content-Type| to |r|'s response's header list." // https://fetch.spec.whatwg.org/#concept-bodyinit-extract // Step 3, Blob: // "If object's type attribute is not the empty byte sequence, set // Content-Type to its value." if (isNullBodyStatus(status)) { exceptionState.throwTypeError("Response with null body status cannot have body"); return nullptr; } r->m_response->replaceBodyStreamBuffer(new BodyStreamBuffer(bodyHandle)); if (!contentType.isEmpty() && !r->m_response->headerList()->has("Content-Type")) r->m_response->headerList()->append("Content-Type", contentType); } // "8. Set |r|'s MIME type to the result of extracting a MIME type // from |r|'s response's header list." r->m_response->setMIMEType(r->m_response->headerList()->extractMIMEType()); // "9. Return |r|." return r; }