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.util.List;
020import java.util.Map;
021import java.util.Optional;
022
023/**
024 * Represents the contents of an HTTP request that is being serviced by a Cloud Function.
025 */
026public interface HttpRequest extends HttpMessage {
027    /**
028     * The HTTP method of this request, such as {@code "POST"} or {@code "GET"}.
029     *
030     * @return the HTTP method of this request.
031     */
032    String getMethod();
033
034    /**
035     * The full URI of this request as it arrived at the server.
036     *
037     * @return the full URI of this request.
038     */
039    String getUri();
040
041    /**
042     * The path part of the URI for this request, without any query. If the full URI is {@code
043     * http://foo.com/bar/baz?this=that}, then this method will return {@code /bar/baz}.
044     *
045     * @return the path part of the URI for this request.
046     */
047    String getPath();
048
049    /**
050     * The query part of the URI for this request. If the full URI is {@code
051     * http://foo.com/bar/baz?this=that}, then this method will return {@code this=that}. If there is
052     * no query part, the returned {@code Optional} is empty.
053     *
054     * @return the query part of the URI, if any.
055     */
056    Optional<String> getQuery();
057
058    /**
059     * The query parameters of this request. If the full URI is {@code
060     * http://foo.com/bar?thing=thing1&thing=thing2&cat=hat}, then the returned map will map {@code
061     * thing} to the list {@code ["thing1", "thing2"]} and {@code cat} to the list with the single
062     * element {@code "hat"}.
063     *
064     * @return a map where each key is the name of a query parameter and the corresponding {@code
065     * List} value indicates every value that was associated with that name.
066     */
067    Map<String, List<String>> getQueryParameters();
068
069    /**
070     * The first query parameter with the given name, if any. If the full URI is {@code
071     * http://foo.com/bar?thing=thing1&thing=thing2&cat=hat}, then {@code
072     * getFirstQueryParameter("thing")} will return {@code Optional.of("thing1")} and {@code
073     * getFirstQueryParameter("something")} will return {@code Optional.empty()}. This is a more
074     * convenient alternative to {@link #getQueryParameters}.
075     *
076     * @param name a query parameter name.
077     * @return the first query parameter value with the given name, if any.
078     */
079    default Optional<String> getFirstQueryParameter(String name) {
080        List<String> parameters = getQueryParameters().get(name);
081        if (parameters == null || parameters.isEmpty()) {
082            return Optional.empty();
083        }
084        return Optional.of(parameters.get(0));
085    }
086
087    /**
088     * Represents one part inside a multipart ({@code multipart/form-data}) HTTP request. Each such
089     * part can have its own HTTP headers, which can be retrieved with the methods inherited from
090     * {@link HttpMessage}.
091     */
092    interface HttpPart extends HttpMessage {
093        /**
094         * Returns the filename associated with this part, if any.
095         *
096         * @return the filename associated with this part, if any.
097         */
098        Optional<String> getFileName();
099    }
100
101    /**
102     * Returns the parts inside this multipart ({@code multipart/form-data}) HTTP request. Each entry
103     * in the returned map has the name of the part as its key and the contents as the associated
104     * value.
105     *
106     * @return a map from part names to part contents.
107     * @throws IllegalStateException if the {@link #getContentType() content type} is not {@code
108     *                               multipart/form-data}.
109     */
110    Map<String, HttpPart> getParts();
111}