All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.vertx.core.http.RequestOptions Maven / Gradle / Ivy

There is a newer version: 5.0.0.CR1
Show newest version
/*
 * Copyright (c) 2011-2019 Contributors to the Eclipse Foundation
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
 * which is available at https://www.apache.org/licenses/LICENSE-2.0.
 *
 * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
 */

package io.vertx.core.http;

import io.vertx.codegen.annotations.DataObject;
import io.vertx.codegen.annotations.GenIgnore;
import io.vertx.codegen.json.annotations.JsonGen;
import io.vertx.core.MultiMap;
import io.vertx.core.VertxException;
import io.vertx.core.json.JsonObject;
import io.vertx.core.net.ProxyOptions;
import io.vertx.core.net.SocketAddress;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static io.vertx.codegen.annotations.GenIgnore.PERMITTED_TYPE;

/**
 * Options describing how an {@link HttpClient} will connect to make a request.
 *
 * @author Julien Viet
 */
@DataObject
@JsonGen(publicConverter = false)
public class RequestOptions {

  /**
   * The default value for proxy options = {@code null}
   */
  public static final ProxyOptions DEFAULT_PROXY_OPTIONS = null;

  /**
   * The default value for server method = {@code null}
   */
  public static final SocketAddress DEFAULT_SERVER = null;

  /**
   * The default value for HTTP method = {@link HttpMethod#GET}
   */
  public static final HttpMethod DEFAULT_HTTP_METHOD = HttpMethod.GET;

  /**
   * The default value for host name = {@code null}
   */
  public static final String DEFAULT_HOST = null;

  /**
   * The default value for port = {@code null}
   */
  public static final Integer DEFAULT_PORT = null;

  /**
   * The default value for SSL = {@code null}
   */
  public static final Boolean DEFAULT_SSL = null;

  /**
   * The default request URI = {@code "/"}
   */
  public static final String DEFAULT_URI = "/";

  /**
   * Follow redirection by default = {@code false}
   */
  public static final boolean DEFAULT_FOLLOW_REDIRECTS = false;

  /**
   * The default request timeout = {@code -1L} (disabled)
   */
  public static final long DEFAULT_TIMEOUT = -1L;

  /**
   * The default connect timeout = {@code -1L} (disabled)
   */
  public static final long DEFAULT_CONNECT_TIMEOUT = -1L;

  /**
   * The default idle timeout = {@code -1L} (disabled)
   */
  public static final long DEFAULT_IDLE_TIMEOUT = -1L;

  private ProxyOptions proxyOptions;
  private SocketAddress server;
  private HttpMethod method;
  private String host;
  private Integer port;
  private Boolean ssl;
  private String uri;
  private MultiMap headers;
  private boolean followRedirects;
  private long timeout;
  private long connectTimeout;
  private long idleTimeout;
  private String traceOperation;

  /**
   * Default constructor
   */
  public RequestOptions() {
    proxyOptions = DEFAULT_PROXY_OPTIONS;
    server = DEFAULT_SERVER;
    method = DEFAULT_HTTP_METHOD;
    host = DEFAULT_HOST;
    port = DEFAULT_PORT;
    ssl = DEFAULT_SSL;
    uri = DEFAULT_URI;
    followRedirects = DEFAULT_FOLLOW_REDIRECTS;
    timeout = DEFAULT_TIMEOUT;
    connectTimeout = DEFAULT_CONNECT_TIMEOUT;
    idleTimeout = DEFAULT_IDLE_TIMEOUT;
    traceOperation = null;
  }

  /**
   * Copy constructor
   *
   * @param other  the options to copy
   */
  public RequestOptions(RequestOptions other) {
    setProxyOptions(other.proxyOptions);
    setServer(other.server);
    setMethod(other.method);
    setHost(other.host);
    setPort(other.port);
    setSsl(other.ssl);
    setURI(other.uri);
    setFollowRedirects(other.followRedirects);
    setTimeout(other.timeout);
    setIdleTimeout(other.idleTimeout);
    setConnectTimeout(other.connectTimeout);
    if (other.headers != null) {
      setHeaders(MultiMap.caseInsensitiveMultiMap().setAll(other.headers));
    }
    setTraceOperation(other.traceOperation);
  }

  /**
   * Create options from JSON
   *
   * @param json the JSON
   */
  public RequestOptions(JsonObject json) {
    this();
    RequestOptionsConverter.fromJson(json, this);
    String method = json.getString("method");
    if (method != null) {
      setMethod(HttpMethod.valueOf(method));
    }
    JsonObject server = json.getJsonObject("server");
    if (server != null) {
      Integer port = server.getInteger("port", 80);
      String host = server.getString("host");
      String path = server.getString("path");
      if (host != null) {
        this.server = SocketAddress.inetSocketAddress(port, host);
      } else if (path != null) {
        this.server = SocketAddress.domainSocketAddress(path);
      }
    }
    JsonObject headers = json.getJsonObject("headers");
    if (headers != null) {
      for (Map.Entry entry : headers) {
        Object value = entry.getValue();
        if (value instanceof String) {
          this.addHeader(entry.getKey(), (String) value);
        } else if (value instanceof Iterable) {
          for (Object subValue : ((Iterable) value)) {
            if (subValue instanceof String) {
              this.addHeader(entry.getKey(), (String) subValue);
            }
          }
        }
      }
    }
  }

  /**
   * Get the proxy options override for connections
   *
   * @return proxy options override
   */
  public ProxyOptions getProxyOptions() {
    return proxyOptions;
  }

  /**
   * Override the {@link HttpClientOptions#setProxyOptions(ProxyOptions)} proxy options
   * for connections.
   *
   * @param proxyOptions proxy options override object
   * @return a reference to this, so the API can be used fluently
   */
  public RequestOptions setProxyOptions(ProxyOptions proxyOptions) {
    this.proxyOptions = proxyOptions;
    return this;
  }

  /**
   * Get the server address to be used by the client request.
   *
   * @return the server address
   */
  public SocketAddress getServer() {
    return server;
  }

  /**
   * Set the server address to be used by the client request.
   *
   * 

When the server address is {@code null}, the address will be resolved after the {@code host} * property by the Vert.x resolver. * *

Use this when you want to connect to a specific server address without name resolution. * * @return a reference to this, so the API can be used fluently */ public RequestOptions setServer(SocketAddress server) { this.server = server; return this; } /** * Get the HTTP method to be used by the client request. * * @return the HTTP method */ @GenIgnore public HttpMethod getMethod() { return method; } /** * Set the HTTP method to be used by the client request. * * @return a reference to this, so the API can be used fluently */ @GenIgnore public RequestOptions setMethod(HttpMethod method) { this.method = method; return this; } /** * Get the host name to be used by the client request. * * @return the host name */ public String getHost() { return host; } /** * Set the host name to be used by the client request. * * @return a reference to this, so the API can be used fluently */ public RequestOptions setHost(String host) { this.host = host; return this; } /** * Get the port to be used by the client request. * * @return the port */ public Integer getPort() { return port; } /** * Set the port to be used by the client request. * * @return a reference to this, so the API can be used fluently */ public RequestOptions setPort(Integer port) { this.port = port; return this; } /** * @return is SSL/TLS enabled? */ public Boolean isSsl() { return ssl; } /** * Set whether SSL/TLS is enabled. * * @param ssl true if enabled * @return a reference to this, so the API can be used fluently */ public RequestOptions setSsl(Boolean ssl) { this.ssl = ssl; return this; } /** * @return the request relative URI */ public String getURI() { return uri; } /** * Set the request relative URI. * * @param uri the relative uri * @return a reference to this, so the API can be used fluently */ public RequestOptions setURI(String uri) { this.uri = uri; return this; } /** * @return {@code true} when the client should follow redirection */ public Boolean getFollowRedirects() { return followRedirects; } /** * Set whether to follow HTTP redirect * * @param followRedirects whether to follow redirect * @return a reference to this, so the API can be used fluently */ public RequestOptions setFollowRedirects(Boolean followRedirects) { this.followRedirects = followRedirects; return this; } /** * @see #setTimeout(long) */ public long getTimeout() { return timeout; } /** * Sets both connect and idle timeouts for the request * *

    *
  • connect timeout: if the request is not obtained from the client within the timeout period, the {@code Future} * obtained from the client is failed with a {@link java.util.concurrent.TimeoutException}.
  • *
  • idle timeout: if the request does not return any data within the timeout period, the request/response is closed and the * related futures are failed with a {@link java.util.concurrent.TimeoutException}, e.g. {@code Future} * or {@code Future} response body.
  • *
* * The connect and idle timeouts can be set separately using {@link #setConnectTimeout(long)} and {@link #setIdleTimeout(long)} */ public RequestOptions setTimeout(long timeout) { this.timeout = timeout; return this; } /** * @return the amount of time after which, if the request is not obtained from the client within the timeout period, * the {@code Future} obtained from the client is failed with a {@link java.util.concurrent.TimeoutException} */ public long getConnectTimeout() { return connectTimeout; } /** * Sets the amount of time after which, if the request is not obtained from the client within the timeout period, * the {@code Future} obtained from the client is failed with a {@link java.util.concurrent.TimeoutException}. * * Note this is not related to the TCP {@link HttpClientOptions#setConnectTimeout(int)} option, when a request is made against * a pooled HTTP client, the timeout applies to the duration to obtain a connection from the pool to serve the request, the timeout * might fire because the server does not respond in time or the pool is too busy to serve a request. * * @param timeout the amount of time in milliseconds. * @return a reference to this, so the API can be used fluently */ public RequestOptions setConnectTimeout(long timeout) { this.connectTimeout = timeout; return this; } /** * @return the amount of time after which, if the request does not return any data within the timeout period, * the request/response is closed and the related futures are failed with a {@link java.util.concurrent.TimeoutException} */ public long getIdleTimeout() { return idleTimeout; } /** * Sets the amount of time after which, if the request does not return any data within the timeout period, * the request/response is closed and the related futures are failed with a {@link java.util.concurrent.TimeoutException}, * e.g. {@code Future} or {@code Future} response body. * *

The timeout starts after a connection is obtained from the client, similar to calling * {@link HttpClientRequest#idleTimeout(long)}. * * @param timeout the amount of time in milliseconds. * @return a reference to this, so the API can be used fluently */ public RequestOptions setIdleTimeout(long timeout) { this.idleTimeout = timeout; return this; } private URL parseUrl(String surl) { // Note - parsing a URL this way is slower than specifying host, port and relativeURI try { return new URL(surl); } catch (MalformedURLException e) { throw new VertxException("Invalid url: " + surl, e); } } /** * Parse an absolute URI to use, this will update the {@code ssl}, {@code host}, * {@code port} and {@code uri} fields. * * @param absoluteURI the uri to use * @return a reference to this, so the API can be used fluently */ public RequestOptions setAbsoluteURI(String absoluteURI) { Objects.requireNonNull(absoluteURI, "Cannot set a null absolute URI"); URL url = parseUrl(absoluteURI); return setAbsoluteURI(url); } /** * Like {@link #setAbsoluteURI(String)} but using an {@link URL} parameter. * * @param url the uri to use * @return a reference to this, so the API can be used fluently */ @GenIgnore(PERMITTED_TYPE) public RequestOptions setAbsoluteURI(URL url) { Objects.requireNonNull(url, "Cannot set a null absolute URI"); Boolean ssl = Boolean.FALSE; int port = url.getPort(); String relativeUri = url.getPath().isEmpty() ? "/" + url.getFile() : url.getFile(); String protocol = url.getProtocol(); switch (protocol) { case "http": if (port == -1) { port = 80; } break; case "https": { ssl = Boolean.TRUE; if (port == -1) { port = 443; } break; } default: throw new IllegalArgumentException(); } this.uri = relativeUri; this.port = port; this.ssl = ssl; this.host = url.getHost(); return this; } /** * Add a request header. * * @param key the header key * @param value the header value * @return a reference to this, so the API can be used fluently */ @GenIgnore public RequestOptions addHeader(String key, String value) { return addHeader((CharSequence) key, value); } /** * Add a request header. * * @param key the header key * @param value the header value * @return a reference to this, so the API can be used fluently */ @GenIgnore public RequestOptions addHeader(CharSequence key, CharSequence value) { checkHeaders(); Objects.requireNonNull(key, "no null key accepted"); Objects.requireNonNull(value, "no null value accepted"); headers.add(key, value); return this; } @GenIgnore public RequestOptions addHeader(CharSequence key, Iterable values) { checkHeaders(); Objects.requireNonNull(key, "no null key accepted"); Objects.requireNonNull(values, "no null values accepted"); headers.add(key, values); return this; } /** * Set a request header. * * @param key the header key * @param value the header value * @return a reference to this, so the API can be used fluently */ @GenIgnore public RequestOptions putHeader(String key, String value) { return putHeader((CharSequence) key, value); } /** * Set a request header. * * @param key the header key * @param value the header value * @return a reference to this, so the API can be used fluently */ @GenIgnore public RequestOptions putHeader(CharSequence key, CharSequence value) { checkHeaders(); headers.set(key, value); return this; } @GenIgnore public RequestOptions putHeader(CharSequence key, Iterable values) { checkHeaders(); headers.set(key, values); return this; } /** * Add a request header. * * @param key the header key * @return a reference to this, so the API can be used fluently */ @GenIgnore public RequestOptions removeHeader(String key) { return removeHeader((CharSequence) key); } /** * Add a request header. * * @param key the header key * @return a reference to this, so the API can be used fluently */ @GenIgnore public RequestOptions removeHeader(CharSequence key) { if (headers != null) { headers.remove(key); } return this; } /** * Set request headers from a multi-map. * * @param headers the headers * @return a reference to this, so the API can be used fluently */ @GenIgnore public RequestOptions setHeaders(MultiMap headers) { this.headers = headers; return this; } /** * Get the request headers * * @return the headers */ @GenIgnore public MultiMap getHeaders() { return headers; } private void checkHeaders() { if (headers == null) { headers = HttpHeaders.headers(); } } /** * @return the trace operation override */ public String getTraceOperation() { return traceOperation; } /** * Override the operation the tracer use for this request. When no operation is set, the HTTP method is used * instead. * * @param op the override * @return a reference to this, so the API can be used fluently */ public RequestOptions setTraceOperation(String op) { this.traceOperation = op; return this; } public JsonObject toJson() { JsonObject json = new JsonObject(); RequestOptionsConverter.toJson(this, json); if (method != null) { json.put("method", method.name()); } if (this.server != null) { JsonObject server = new JsonObject(); if (this.server.isInetSocket()) { server.put("host", this.server.host()); server.put("port", this.server.port()); } else { server.put("path", this.server.path()); } json.put("server", server); } if (this.headers != null) { JsonObject headers = new JsonObject(); for (String name : this.headers.names()) { List values = this.headers.getAll(name); if (values.size() == 1) { headers.put(name, values.iterator().next()); } else { headers.put(name, values); } } json.put("headers", headers); } return json; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy