001/*
002Copyright 2022 The OpenFunction Authors.
003
004Licensed under the Apache License, Version 2.0 (the "License");
005you may not use this file except in compliance with the License.
006You may obtain a copy of the License at
007
008    http://www.apache.org/licenses/LICENSE-2.0
009
010Unless required by applicable law or agreed to in writing, software
011distributed under the License is distributed on an "AS IS" BASIS,
012WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013See the License for the specific language governing permissions and
014limitations under the License.
015*/
016
017package dev.openfunction.functions;
018
019import java.io.BufferedWriter;
020import java.io.IOException;
021import java.io.OutputStream;
022import java.util.List;
023import java.util.Map;
024import java.util.Optional;
025
026/**
027 * Represents the contents of an HTTP response that is being sent by a Cloud Function in response to
028 * an HTTP request.
029 */
030public interface HttpResponse {
031    /**
032     * Sets the numeric HTTP <a
033     * href="https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml">status
034     * code</a> to use in the response. Most often this will be 200, which is the OK status. The named
035     * constants in {@link java.net.HttpURLConnection}, such as {@link
036     * java.net.HttpURLConnection#HTTP_OK HTTP_OK}, can be used as an alternative to writing numbers
037     * in your source code.
038     *
039     * @param code the status code.
040     */
041    void setStatusCode(int code);
042
043    /**
044     * @return http status code
045     */
046    int getStatusCode();
047
048    /**
049     * Sets the numeric HTTP <a
050     * href="https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml">status
051     * code</a> and reason message to use in the response. For example<br>
052     * {@code setStatusCode(400, "Something went wrong")}. The named constants in {@link
053     * java.net.HttpURLConnection}, such as {@link java.net.HttpURLConnection#HTTP_BAD_REQUEST
054     * HTTP_BAD_REQUEST}, can be used as an alternative to writing numbers in your source code.
055     *
056     * @param code    the status code.
057     * @param message the status message.
058     */
059    void setStatusCode(int code, String message);
060
061    /**
062     * Sets the value to use for the {@code Content-Type} header in the response. This may include a
063     * character encoding, for example {@code setContentType("text/plain; charset=utf-8")}.
064     *
065     * @param contentType the content type.
066     */
067    void setContentType(String contentType);
068
069    /**
070     * Returns the {@code Content-Type} that was previously set by {@link #setContentType}, or by
071     * {@link #appendHeader} with a header name of {@code Content-Type}. If no {@code Content-Type}
072     * has been set, returns {@code Optional.empty()}.
073     *
074     * @return the content type, if any.
075     */
076    Optional<String> getContentType();
077
078    /**
079     * Includes the given header name with the given value in the response. This method may be called
080     * several times for the same header, in which case the response will contain the header the same
081     * number of times.
082     *
083     * @param header an HTTP header, such as {@code Content-Type}.
084     * @param value  a value to associate with that header.
085     */
086    void appendHeader(String header, String value);
087
088    /**
089     * Returns the headers that have been defined for the response so far. This will contain at least
090     * the headers that have been set via {@link #appendHeader} or {@link #setContentType}, and may
091     * contain additional headers such as {@code Date}.
092     *
093     * @return a map where each key is a header name and the corresponding {@code List} value has one
094     * entry for every value associated with that header.
095     */
096    Map<String, List<String>> getHeaders();
097
098    /**
099     * Returns an {@link OutputStream} that can be used to write the body of the response. This method
100     * is typically used to write binary data. If the body is text, the {@link #getWriter()} method is
101     * more appropriate.
102     *
103     * @return the output stream.
104     * @throws IOException           if a valid {@link OutputStream} cannot be returned for some reason.
105     * @throws IllegalStateException if {@link #getWriter} has already been called on this instance.
106     */
107    OutputStream getOutputStream() throws IOException;
108
109    /**
110     * Returns a {@link BufferedWriter} that can be used to write the text body of the response. If
111     * the written text will not be US-ASCII, you should specify a character encoding by calling
112     * {@link #setContentType setContentType("text/foo; charset=bar")} or {@link #appendHeader
113     * appendHeader("Content-Type", "text/foo; charset=bar")} before calling this method.
114     *
115     * @return the writer.
116     * @throws IOException           if a valid {@link BufferedWriter} cannot be returned for some reason.
117     * @throws IllegalStateException if {@link #getOutputStream} has already been called on this
118     *                               instance.
119     */
120    BufferedWriter getWriter() throws IOException;
121}