001// Copyright 2019 Google LLC
002//
003// Licensed under the Apache License, Version 2.0 (the "License");
004// you may not use this file except in compliance with the License.
005// You may obtain a copy of the License at
006//
007//      http://www.apache.org/licenses/LICENSE-2.0
008//
009// Unless required by applicable law or agreed to in writing, software
010// distributed under the License is distributed on an "AS IS" BASIS,
011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012// See the License for the specific language governing permissions and
013// limitations under the License.
014
015package com.google.cloud.functions;
016
017import java.util.List;
018import java.util.Map;
019import java.util.Optional;
020
021/**
022 * Represents the contents of an HTTP request that is being serviced by a Cloud Function.
023 */
024public interface HttpRequest extends HttpMessage {
025  /**
026   * The HTTP method of this request, such as {@code "POST"} or {@code "GET"}.
027   *
028   * @return the HTTP method of this request.
029   */
030  String getMethod();
031
032  /**
033   * The full URI of this request as it arrived at the server.
034   *
035   * @return the full URI of this request.
036   */
037  String getUri();
038
039  /**
040   * The path part of the URI for this request, without any query. If the full URI is
041   * {@code http://foo.com/bar/baz?this=that}, then this method will return {@code /bar/baz}.
042   *
043   * @return the path part of the URI for this request.
044   */
045  String getPath();
046
047  /**
048   * The query part of the URI for this request. If the full URI is
049   * {@code http://foo.com/bar/baz?this=that}, then this method will return {@code this=that}.
050   * If there is no query part, the returned {@code Optional} is empty.
051   *
052   * @return the query part of the URI, if any.
053   */
054  Optional<String> getQuery();
055
056  /**
057   * The query parameters of this request. If the full URI is
058   * {@code http://foo.com/bar?thing=thing1&thing=thing2&cat=hat}, then the returned map will map
059   * {@code thing} to the list {@code ["thing1", "thing2"]} and {@code cat} to the list with the
060   * single element {@code "hat"}.
061   *
062   * @return a map where each key is the name of a query parameter and the corresponding
063   *     {@code List} value indicates every value that was associated with that name.
064   */
065  Map<String, List<String>> getQueryParameters();
066
067  /**
068   * The first query parameter with the given name, if any. If the full URI is
069   * {@code http://foo.com/bar?thing=thing1&thing=thing2&cat=hat}, then
070   * {@code getFirstQueryParameter("thing")} will return {@code Optional.of("thing1")} and
071   * {@code getFirstQueryParameter("something")} will return {@code Optional.empty()}. This is a
072   * more convenient alternative to {@link #getQueryParameters}.
073   *
074   * @param name a query parameter name.
075   * @return the first query parameter value with the given name, if any.
076   */
077  default Optional<String> getFirstQueryParameter(String name) {
078    List<String> parameters = getQueryParameters().get(name);
079    if (parameters == null || parameters.isEmpty()) {
080      return Optional.empty();
081    }
082    return Optional.of(parameters.get(0));
083  }
084
085  /**
086   * Represents one part inside a multipart ({@code multipart/form-data}) HTTP request. Each such
087   * part can have its own HTTP headers, which can be retrieved with the methods inherited from
088   * {@link HttpMessage}.
089   */
090  interface HttpPart extends HttpMessage {
091    /**
092     * Returns the filename associated with this part, if any.
093     *
094     * @return the filename associated with this part, if any.
095     */
096    Optional<String> getFileName();
097  }
098
099  /**
100   * Returns the parts inside this multipart ({@code multipart/form-data}) HTTP request. Each entry
101   * in the returned map has the name of the part as its key and the contents as the associated
102   * value.
103   *
104   * @return a map from part names to part contents.
105   * @throws IllegalStateException if the {@link #getContentType() content type} is not
106   *     {@code multipart/form-data}.
107   */
108  Map<String, HttpPart> getParts();
109}