All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.dromara.hutool.http.HttpUtil Maven / Gradle / Ivy
/*
* Copyright (c) 2013-2024 Hutool Team and hutool.cn
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.dromara.hutool.http;
import org.dromara.hutool.core.collection.CollUtil;
import org.dromara.hutool.core.map.CaseInsensitiveMap;
import org.dromara.hutool.core.map.MapUtil;
import org.dromara.hutool.core.net.url.UrlQueryUtil;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.http.client.ClientConfig;
import org.dromara.hutool.http.client.Request;
import org.dromara.hutool.http.client.Response;
import org.dromara.hutool.http.client.engine.ClientEngine;
import org.dromara.hutool.http.client.engine.ClientEngineFactory;
import org.dromara.hutool.http.meta.Method;
import org.dromara.hutool.http.server.SimpleServer;
import java.nio.charset.Charset;
import java.util.Collection;
import java.util.Map;
/**
* Http请求工具类
*
* @author Looly
*/
public class HttpUtil {
/**
* 检测是否https
*
* @param url URL
* @return 是否https
*/
public static boolean isHttps(final String url) {
return StrUtil.startWithIgnoreCase(url, "https:");
}
/**
* 检测是否http
*
* @param url URL
* @return 是否http
* @since 5.3.8
*/
public static boolean isHttp(final String url) {
return StrUtil.startWithIgnoreCase(url, "http:");
}
/**
* 创建Http请求对象
*
* @param method 方法枚举{@link Method}
* @param url 请求的URL,可以使HTTP或者HTTPS
* @return {@link Request}
*/
public static Request createRequest(final String url, final Method method) {
return Request.of(url).method(method);
}
/**
* 创建Http GET请求对象
*
* @param url 请求的URL,可以使HTTP或者HTTPS
* @return {@link Request}
*/
public static Request createGet(final String url) {
return createRequest(url, Method.GET);
}
/**
* 创建Http POST请求对象
*
* @param url 请求的URL,可以使HTTP或者HTTPS
* @return {@link Request}
*/
public static Request createPost(final String url) {
return createRequest(url, Method.POST);
}
/**
* 发送get请求
*
* @param urlString 网址
* @param customCharset 自定义请求字符集,如果字符集获取不到,使用此字符集
* @return 返回内容,如果只检查状态码,正常只返回 "",不正常返回 null
*/
@SuppressWarnings("resource")
public static String get(final String urlString, final Charset customCharset) {
return send(Request.of(urlString).charset(customCharset)).bodyStr();
}
/**
* 发送get请求
*
* @param urlString 网址
* @return 返回内容,如果只检查状态码,正常只返回 "",不正常返回 null
*/
@SuppressWarnings("resource")
public static String get(final String urlString) {
return ClientEngineFactory.getEngine().send(Request.of(urlString)).bodyStr();
}
/**
* 发送get请求
*
* @param urlString 网址
* @param timeout 超时时长,-1表示默认超时,单位毫秒
* @return 返回内容,如果只检查状态码,正常只返回 "",不正常返回 null
* @since 3.2.0
*/
@SuppressWarnings("resource")
public static String get(final String urlString, final int timeout) {
// 创建自定义客户端
return ClientEngineFactory.createEngine()
.init(ClientConfig.of().setConnectionTimeout(timeout).setReadTimeout(timeout))
.send(Request.of(urlString)).bodyStr();
}
/**
* 发送get请求
*
* @param urlString 网址
* @param paramMap post表单数据
* @return 返回数据
*/
@SuppressWarnings("resource")
public static String get(final String urlString, final Map paramMap) {
return send(Request.of(urlString).form(paramMap))
.bodyStr();
}
/**
* 发送post请求
*
* @param urlString 网址
* @param paramMap post表单数据
* @return 返回数据
*/
@SuppressWarnings("resource")
public static String post(final String urlString, final Map paramMap) {
return send(Request.of(urlString).method(Method.POST).form(paramMap))
.bodyStr();
}
/**
* 发送post请求
* 请求体body参数支持两种类型:
*
*
* 1. 标准参数,例如 a=1&b=2 这种格式
* 2. Rest模式,此时body需要传入一个JSON或者XML字符串,Hutool会自动绑定其对应的Content-Type
*
*
* @param urlString 网址
* @param body post表单数据
* @return 返回数据
*/
@SuppressWarnings("resource")
public static String post(final String urlString, final String body) {
return send(Request.of(urlString).method(Method.POST).body(body))
.bodyStr();
}
/**
* 发送post请求
* 请求体body参数支持两种类型:
*
*
* 1. 标准参数,例如 a=1&b=2 这种格式
* 2. Rest模式,此时body需要传入一个JSON或者XML字符串,Hutool会自动绑定其对应的Content-Type
*
*
* @param urlString 网址
* @param body post表单数据
* @param timeout 超时时长,-1表示默认超时,单位毫秒
* @return 返回数据
*/
@SuppressWarnings("resource")
public static String post(final String urlString, final String body, final int timeout) {
// 创建自定义客户端
return ClientEngineFactory.createEngine()
.init(ClientConfig.of().setConnectionTimeout(timeout).setReadTimeout(timeout))
.send(Request.of(urlString).method(Method.POST).body(body)).bodyStr();
}
/**
* 使用默认HTTP引擎,发送HTTP请求
*
* @param request HTTP请求
* @return HTTP响应
*/
public static Response send(final Request request) {
return ClientEngineFactory.getEngine().send(request);
}
/**
* 将表单数据加到URL中(用于GET表单提交)
* 表单的键值对会被url编码,但是url中原参数不会被编码
* 且对form参数进行 FormUrlEncoded ,x-www-form-urlencoded模式,此模式下空格会编码为'+'
*
* @param url URL
* @param form 表单数据
* @param charset 编码 null表示不encode键值对
* @return 合成后的URL
*/
public static String urlWithFormUrlEncoded(final String url, final Map form, final Charset charset) {
return urlWithForm(url, form, charset, true);
}
/**
* 将表单数据加到URL中(用于GET表单提交)
* 表单的键值对会被url编码,但是url中原参数不会被编码
*
* @param url URL
* @param form 表单数据
* @param charset 编码
* @param isEncodeParams 是否对键和值做转义处理
* @return 合成后的URL
*/
public static String urlWithForm(final String url, final Map form, final Charset charset, final boolean isEncodeParams) {
return urlWithForm(url, UrlQueryUtil.toQuery(form, null), charset, isEncodeParams);
}
/**
* 将表单数据字符串加到URL中(用于GET表单提交)
*
* @param url URL
* @param queryString 表单数据字符串
* @param charset 编码
* @param isEncode 是否对键和值做转义处理
* @return 拼接后的字符串
*/
public static String urlWithForm(final String url, final String queryString, final Charset charset, final boolean isEncode) {
if (StrUtil.isBlank(queryString)) {
// 无额外参数
if (StrUtil.contains(url, '?')) {
// url中包含参数
return isEncode ? UrlQueryUtil.encodeQuery(url, charset) : url;
}
return url;
}
// 始终有参数
final StringBuilder urlBuilder = new StringBuilder(url.length() + queryString.length() + 16);
final int qmIndex = url.indexOf('?');
if (qmIndex > 0) {
// 原URL带参数,则对这部分参数单独编码(如果选项为进行编码)
urlBuilder.append(isEncode ? UrlQueryUtil.encodeQuery(url, charset) : url);
if (!StrUtil.endWith(url, '&')) {
// 已经带参数的情况下追加参数
urlBuilder.append('&');
}
} else {
// 原url无参数,则不做编码
urlBuilder.append(url);
if (qmIndex < 0) {
// 无 '?' 追加之
urlBuilder.append('?');
}
}
urlBuilder.append(isEncode ? UrlQueryUtil.encodeQuery(queryString, charset) : queryString);
return urlBuilder.toString();
}
/**
* 创建客户端引擎
*
* @param engineName 引擎名称
* @return {@link ClientEngine}
*/
public static ClientEngine createClient(final String engineName) {
return ClientEngineFactory.createEngine(engineName);
}
/**
* 创建简易的Http服务器
*
* @param port 端口
* @return {@link SimpleServer}
* @since 5.2.6
*/
public static SimpleServer createServer(final int port) {
return new SimpleServer(port);
}
/**
* 打印{@link Response} 为可读形式
*
* @param response {@link Response}
* @return 字符串
*/
public static String toString(final Response response) {
final StringBuilder sb = StrUtil.builder();
sb.append("Response Status: ").append(response.getStatus()).append(StrUtil.CRLF);
// header
sb.append("Response Headers: ").append(StrUtil.CRLF);
response.headers().forEach((key, value) -> sb.append(" ").append(key).append(": ").append(CollUtil.join(value, ",")).append(StrUtil.CRLF));
// body
sb.append("Response Body: ").append(StrUtil.CRLF);
sb.append(" ").append(response.bodyStr()).append(StrUtil.CRLF);
return sb.toString();
}
/**
* 打印 {@link Request} 为可读形式
*
* @param request {@link Request}
* @return 字符串
*/
public static String toString(final Request request) {
final StringBuilder sb = StrUtil.builder();
sb.append("Request Url: ").append(request.url()).append(StrUtil.CRLF);
// header
sb.append("Request Headers: ").append(StrUtil.CRLF);
request.headers().forEach((key, value) -> sb.append(" ").append(key).append(": ").append(CollUtil.join(value, ",")).append(StrUtil.CRLF));
// body
sb.append("Request Body: ").append(StrUtil.CRLF);
sb.append(" ").append(request.bodyStr()).append(StrUtil.CRLF);
return sb.toString();
}
/**
* 获取指定的Header值,如果不存在返回{@code null}
* 根据RFC2616规范,header的name不区分大小写,因此首先get值,不存在则遍历匹配不区分大小写的key。
*
* @param headers 头信息的Map
* @param name header名
* @return header值
* @since 6.0.0
*/
public static String header(final Map> headers, final String name) {
Collection values = headers.get(name);
if (null == values && !(headers instanceof CaseInsensitiveMap)) {
// issue#I96U4T,根据RFC2616规范,header的name不区分大小写
values = MapUtil.firstMatchValue(headers, entry -> StrUtil.equalsIgnoreCase(name, entry.getKey()));
}
if (CollUtil.isNotEmpty(values)) {
return CollUtil.getFirst(values);
}
return null;
}
}