简体   繁体   中英

Use CORS in a http request

Today, i have the following problem. I want to make an http request to an rest api, but I only get an 405 error. I searched and i found, that the api use cors. So how i can make a http request with cors?

Here is my http client:

package community.opencode.minetools4j.util.http;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NonNull;
import org.apache.commons.io.IOUtils;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

/**
 * This is an utility class.
 * It simplify making HTTP requests
 */
public class HttpRequest {

    /**
     * Performs a new HTTP request
     *
     * @param requestBuilder See {@link RequestBuilder}
     * @return See {@link RequestResponse}
     * @throws IOException Will be thrown if the request can't be executed
     */
    public static RequestResponse performRequest(RequestBuilder requestBuilder) throws IOException {
        URL newUrl = new URL(requestBuilder.getPath());

        HttpURLConnection connection = (HttpURLConnection) newUrl.openConnection();
        connection.setRequestMethod(requestBuilder.getMethod().getType());
        requestBuilder.getHeaders().forEach(connection::setRequestProperty);
        connection.setConnectTimeout(5000);
        connection.setReadTimeout(5000);
        connection.setDoOutput(true);

        DataOutputStream out = new DataOutputStream(connection.getOutputStream());
        out.writeBytes(getParametersString(requestBuilder.getParams()));

        int status = connection.getResponseCode();
        String result = IOUtils.toString(connection.getInputStream(), "UTF-8");
        String contentType = connection.getHeaderField("Content-Type");
        connection.getInputStream().close();
        connection.disconnect();
        return new RequestResponse(status, result, contentType);
    }

    /**
     * Makes from a map a valid HTTP string
     * Example: "myField=Hey!&myPassword=abc"
     *
     * @param params The parameters
     * @return The formed String
     * @throws UnsupportedEncodingException Should never be thrown
     */
    private static String getParametersString(Map<String, String> params) throws UnsupportedEncodingException {
        StringBuilder builder = new StringBuilder();
        for (Map.Entry<String, String> entry : params.entrySet()) {
            builder.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
            builder.append("=");
            builder.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
            builder.append("&");
        }
        String result = builder.toString();
        return result.length() > 0 ? result.substring(0, result.length() - 1) : result;
    }

    /**
     * A simple builder class for {@link #performRequest(RequestBuilder)}
     */
    @Data
    public static class RequestBuilder {

        private final String path;
        private final HttpRequestMethod method;

        private final Map<String, String> params = new HashMap<>();
        private final Map<String, String> headers = new HashMap<>();

        public RequestBuilder addParam(@NonNull String name, @NonNull String value) {
            this.params.put(name, value);
            return this;
        }

        public RequestBuilder addHeader(@NonNull String name, @NonNull String value) {
            this.headers.put(name, value);
            return this;
        }
    }

    /**
     * A simplified http response.
     * Including status, message and the returned content type
     */
    @Data
    @AllArgsConstructor
    public static class RequestResponse {

        private int status;
        private String resultMessage;
        private String contentType;
    }
}

package community.opencode.minetools4j.util.http;

import lombok.Getter;

/**
 * Simple enum for {@link HttpRequest}.
 * It's a better way than just write manually the method name
 */
public enum HttpRequestMethod {
    POST("POST"),
    GET("GET"),
    PUT("PUT"),
    HEAD("HEAD"),
    OPTIONS("OPTIONS"),
    DELETE("DELETE"),
    TRACE("TRACE");

    @Getter
    private String type;

    HttpRequestMethod(String type) {
        this.type = type;
    }
}

And here is my method to make a http request:

HttpRequest.RequestResponse requestResponse = HttpRequest.performRequest(new HttpRequest.RequestBuilder(API_URI + "/ping/" + host + "/" + port, HttpRequestMethod.GET));

Thank you for your attention.

Sincerely, Skyleiger

Sorry for my bad english. I hope you can understand me ;)

if you are getting this type of error:

Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin ' http://localhost:4200 ' is therefore not allowed access. The response had HTTP status code 405.

You will have to create a servlet filter and add the code below on the doFilter method.

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
        throws IOException, ServletException {
    HttpServletRequest request = (HttpServletRequest) servletRequest;

    HttpServletResponse resp = (HttpServletResponse) servletResponse;
    resp.addHeader("Access-Control-Allow-Origin", "*");
    resp.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE,HEAD");
    resp.addHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    resp.addHeader("Accept-Encoding", "multipart/form-data");

    if (request.getMethod().equals("OPTIONS")) {
        resp.setStatus(200);
        return;
    }
    chain.doFilter(request, servletResponse);
  }

What is HTTP code 405

Status 405 means the method you are using isn't allowed on the request you sent.

Source

How to fix

You'll need to check the API docs to see if you have one of these wrong:

  • Missing Auth headers
  • Missing content
  • Wrong URL
  • Wrong method

Simplifying code

Using unirest may simplify your request code, and cover edge cases

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM