aboutsummaryrefslogtreecommitdiffstats
path: root/container-core/src/main/java/com/yahoo/container/jdisc/HttpResponse.java
blob: 2671f4e131ab518c89c8926f659d75a9a1ecff2f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.container.jdisc;

import com.yahoo.container.logging.AccessLogEntry;
import com.yahoo.jdisc.HeaderFields;
import com.yahoo.jdisc.Request;
import com.yahoo.jdisc.Response;
import com.yahoo.processing.execution.Execution.Trace.LogValue;

import java.io.IOException;
import java.io.OutputStream;
import java.util.Collections;

/**
 * An HTTP response as an opaque payload with headers and content type.
 *
 * @author hmusum
 * @author Steinar Knutsen
 */
public abstract class HttpResponse {

    /** Default response content type; text/plain. */
    public static final String DEFAULT_MIME_TYPE = "text/plain";

    /** Default encoding/character set of a HTTP response; UTF-8. */
    public static final String DEFAULT_CHARACTER_ENCODING = "UTF-8";

    private final Response parentResponse;

    /**
     * Creates a new HTTP response
     *
     * @param status the HTTP status code to return with this response (may be changed later)
     * @see Response
     */
    public HttpResponse(int status) {
        parentResponse = com.yahoo.jdisc.http.HttpResponse.newInstance(status);
    }

    /** Marshals this response to the network layer. The caller is responsible for flushing and closing outputStream. */
    public abstract void render(OutputStream outputStream) throws IOException;

    /** The amount of content bytes this response may have in-flight (if positive) before response rendering blocks. */
    public long maxPendingBytes() { return -1; }

    /**
     * Returns the numeric HTTP status code, e.g. 200, 404 and so on.
     *
     * @return the numeric HTTP status code
     */
    public int getStatus() {
        return parentResponse.getStatus();
    }

    /**
     * Sets the numeric HTTP status code this will return.
     */
    public void setStatus(int status) { parentResponse.setStatus(status); }

    /**
     * The response headers.
     *
     * @return a mutable, thread-unsafe view of the response headers
     */
    public HeaderFields headers() {
        return parentResponse.headers();
    }

    /**
     * The underlying JDisc response.
     *
     * @return the actual response which will be used by the JDisc layer
     */
    public com.yahoo.jdisc.Response getJdiscResponse() {
        return parentResponse;
    }

    /**
     * The MIME type of the response contents or null. If null is returned, no
     * content type header is added to the HTTP response.
     *
     * @return by default {@link HttpResponse#DEFAULT_MIME_TYPE}
     */
    public String getContentType() {
        return DEFAULT_MIME_TYPE;
    }

    /**
     * The name of the encoding for the response contents, if applicable. Return
     * null if character set is not applicable to the response in question (e.g.
     * binary formats). If null is returned, not "charset" element is added to
     * the content type header.
     *
     * @return by default {@link HttpResponse#DEFAULT_CHARACTER_ENCODING}
     */
    public String getCharacterEncoding() {
        return DEFAULT_CHARACTER_ENCODING;
    }

    // ========================================
    // Purely optional stuff from this point on
    // ========================================

    /**
     * Override this method to add information from the response to the access log.
     *
     * Remember to also invoke super if you override it.
     *
     * @param accessLogEntry the access log entry to add information to.
     */
    public void populateAccessLogEntry(final AccessLogEntry accessLogEntry) {
        for (LogValue logValue : getLogValues()) {
            accessLogEntry.addKeyValue(logValue.getKey(), logValue.getValue());
        }
    }

    /**
     * Complete creation of this response.
     * This is called by the container once just before writing the response header back to the caller,
     * so this is the last moment at which status and headers can be determined.
     * This default implementation does nothing.
     */
    public void complete() { }

    public Iterable<LogValue> getLogValues() {
        return Collections::emptyIterator;
    }

    /** Sets the type classification of this request for metric collection purposes */
    public void setRequestType(Request.RequestType requestType) { parentResponse.setRequestType(requestType); }

    /**
     * Returns the type classification of this request for metric collection purposes, or null if not set.
     * When not set, the request type will be "read" for GET requests and "write" for other request methods.
     */
    public Request.RequestType getRequestType() { return parentResponse.getRequestType(); }

}