Exemple #1
0
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;
}