| | |
| | | package com.ruoyi.web.controller.tool; |
| | | |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.ruoyi.common.constant.HttpStatus; |
| | | import com.ruoyi.common.core.domain.model.LoginUser; |
| | | import com.ruoyi.common.exception.ServiceException; |
| | | import com.ruoyi.common.utils.SecurityUtils; |
| | | import okhttp3.FormBody; |
| | | import okhttp3.HttpUrl; |
| | | import okhttp3.MediaType; |
| | |
| | | */ |
| | | public final class BaseDataApiUtil { |
| | | |
| | | public static final String DEFAULT_BASE_URL = "http://192.168.1.160:18888"; |
| | | public static final String DEFAULT_BASE_URL = "http://58.20.112.148:18888"; |
| | | private static final String BASE_URL_PROPERTY = "base.data.api.url"; |
| | | private static final String BASE_URL_ENV = "BASE_DATA_API_URL"; |
| | | private static final String AUTHORIZATION_HEADER = "Authorization"; |
| | | private static final String BEARER_PREFIX = "Bearer "; |
| | | private static final MediaType JSON_MEDIA_TYPE = MediaType.parse("application/json; charset=utf-8"); |
| | | private static final MediaType OCTET_STREAM_MEDIA_TYPE = MediaType.parse("application/octet-stream"); |
| | | private static final OkHttpClient CLIENT = new OkHttpClient.Builder() |
| | |
| | | requireContentType(api, RequestContentType.MULTIPART); |
| | | String url = buildUrl(baseUrl, api.getPath(), pathVariables, null); |
| | | Request.Builder requestBuilder = new Request.Builder().url(url); |
| | | addHeaders(requestBuilder, headers); |
| | | addHeaders(requestBuilder, api, headers); |
| | | applyMethod(requestBuilder, api.getMethod(), buildMultipartBody(fields, files)); |
| | | return executeString(requestBuilder.build()); |
| | | } |
| | |
| | | */ |
| | | private static Request buildRequest(String baseUrl, Api api, Map<String, ?> pathVariables, |
| | | Map<String, ?> params, Object explicitBody, |
| | | Map<String, String> headers) { |
| | | Map<String, String> headers) throws IOException { |
| | | Objects.requireNonNull(api, "api"); |
| | | if (api.getRequestContentType() == RequestContentType.MULTIPART) { |
| | | throw new IllegalArgumentException("multipart/form-data 接口请使用 requestMultipart 方法"); |
| | |
| | | String url = buildUrl(baseUrl, api.getPath(), pathVariables, queryParamRequest ? params : null); |
| | | RequestBody body = queryParamRequest ? null : buildRequestBody(api, params, explicitBody); |
| | | Request.Builder requestBuilder = new Request.Builder().url(url); |
| | | addHeaders(requestBuilder, headers); |
| | | addHeaders(requestBuilder, api, headers); |
| | | applyMethod(requestBuilder, api.getMethod(), body); |
| | | return requestBuilder.build(); |
| | | } |
| | |
| | | /** |
| | | * 目的:追加自定义请求头,过滤空 header 名和空 header 值。 |
| | | */ |
| | | private static void addHeaders(Request.Builder builder, Map<String, String> headers) { |
| | | private static void addHeaders(Request.Builder builder, Api api, Map<String, String> headers) throws IOException { |
| | | addMiddlePlatformAuthorization(builder, api, headers); |
| | | if (headers == null) { |
| | | return; |
| | | } |
| | | for (Map.Entry<String, String> entry : headers.entrySet()) { |
| | | if (isNotBlank(entry.getKey()) && entry.getValue() != null) { |
| | | if (isNotBlank(entry.getKey()) && isNotBlank(entry.getValue())) { |
| | | builder.header(entry.getKey(), entry.getValue()); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 目的:除登录接口外,为所有中台请求统一添加当前登录态的 Bearer Token。 |
| | | */ |
| | | private static void addMiddlePlatformAuthorization(Request.Builder builder, Api api, |
| | | Map<String, String> headers) throws IOException { |
| | | Objects.requireNonNull(api, "api"); |
| | | if (api == Api.POST_AUTH_USER_LOGIN || hasAuthorizationHeader(headers)) { |
| | | return; |
| | | } |
| | | |
| | | LoginUser loginUser; |
| | | try { |
| | | loginUser = SecurityUtils.getLoginUser(); |
| | | } catch (RuntimeException e) { |
| | | throw new ServiceException("中台认证信息已失效,请重新登录", HttpStatus.UNAUTHORIZED); |
| | | } |
| | | String token = loginUser == null ? null : loginUser.getMiddlePlatformToken(); |
| | | if (!isNotBlank(token)) { |
| | | if (loginUser != null && "local".equalsIgnoreCase(loginUser.getLoginSource())) { |
| | | throw new ServiceException("当前账号未通过中台认证,无法查询中台数据", HttpStatus.FORBIDDEN); |
| | | } |
| | | throw new ServiceException("中台认证信息已失效,请重新登录", HttpStatus.UNAUTHORIZED); |
| | | } |
| | | builder.header(AUTHORIZATION_HEADER, BEARER_PREFIX + token.trim()); |
| | | } |
| | | |
| | | /** |
| | | * 目的:允许调用方显式传入认证头,并由后续自定义请求头处理覆盖默认值。 |
| | | */ |
| | | private static boolean hasAuthorizationHeader(Map<String, String> headers) { |
| | | if (headers == null) { |
| | | return false; |
| | | } |
| | | for (Map.Entry<String, String> entry : headers.entrySet()) { |
| | | if (AUTHORIZATION_HEADER.equalsIgnoreCase(entry.getKey()) && isNotBlank(entry.getValue())) { |
| | | return true; |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | /** |
| | | * 目的:执行请求并读取字符串响应,非 2xx 响应统一转为 IOException。 |
| | | */ |
| | | private static String executeString(Request request) throws IOException { |