如何通过假客户端(ApacheHttpClient)向odata发送带空格的请求参数

问题描述 投票:0回答:0

我想通过带有 $filter 参数的 odata 发送 GET 请求 (

$filter=cast(Договор_Key,'Catalog_Договоры') eq guid'<UUID>'
)。如您所见,url 中有两个空格。 在日志上假装显示网址:https://mysite/odata/standard.odata/Document_%D0%A1%D1%87%D0%B5%D1%82%D0%A4%D0%B0%D0%BA%D1 %82%D1%83%D1%80%D0%B0%D0%92%D1%8B%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9?%24format= json%3Bodata%3Dnometadata&%24inlinecount=allpages&%24filter=cast%28%D0%94%D0%BE%D0%B3%D0%BE%D0%B2%D0%BE%D1%80_Key%2C%27Catalog_%D0% 94%D0%BE%D0%B3%D0%BE%D0%B2%D0%BE%D1%80%D1%8B%27%29%20eq%20guid%27e1004688-92d7-11ed-8f65-005056992589%27

此 URL 在 firefox 上正常工作,但我的 java 应用程序抛出错误:

feign.FeignException$InternalServerError: [500 Internal server error] during [GET] to [https://mysite/odata/standard.odata/Document_%D0%A1%D1%87%D0%B5%D1%82%D0%A4%D0%B0%D0%BA%D1%82%D1%83%D1%80%D0%B0%D0%92%D1%8B%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9?%24format=json%3Bodata%3Dnometadata&%24inlinecount=allpages&%24filter=cast%28%D0%94%D0%BE%D0%B3%D0%BE%D0%B2%D0%BE%D1%80_Key%2C%27Catalog_%D0%94%D0%BE%D0%B3%D0%BE%D0%B2%D0%BE%D1%80%D1%8B%27%29%20eq%20guid%27e1004688-92d7-11ed-8f65-005056992589%27] [OdataClient#getTaxInvoiceByContractId(String,String,String,String)]: [{
"odata.error": {
"code": "-1",
"message": {
"lang": "ru",
"value": "{(3, 2)}: Операция не разрешена в предложении \"ГДЕ\"\n<<?>>CAST( sourceAlias.Договор AS Catalog.Договоры )"
}
}

}]

我不明白,为什么它在浏览器上有效,但在我的应用程序中却无效。

我正在使用:

SpringBoot 3.0.5
,
spring-cloud-starter-openfeign 4.0.1
,
io.github.openfeign.feign-httpclient 12.2
.

Feign 配置类。我定制了我的 Feign 客户端以禁用 SSL,因此添加了

io.github.openfeign.feign-httpclient 12.2
依赖项。

import feign.Feign;
import feign.Logger;
import feign.httpclient.ApacheHttpClient;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.impl.client.HttpClientBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;

@Configuration
public class FeignClientConfig {

    @Bean
    public ApacheHttpClient apacheFeignClient() throws NoSuchAlgorithmException, KeyManagementException {
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, new TrustManager[]{new X509TrustManager() {
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }

            public void checkClientTrusted(X509Certificate[] certs, String authType) {
            }

            public void checkServerTrusted(X509Certificate[] certs, String authType) {
            }
        }}, new SecureRandom());

        HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;

        return new ApacheHttpClient(HttpClientBuilder.create()
                .setSSLContext(sslContext)
                .setSSLHostnameVerifier(hostnameVerifier)
                .build());
    }

    @Bean
    public Feign.Builder feignBuilder() throws Exception {
        return Feign.builder()
                .client(apacheFeignClient());
    }

    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.BASIC;
    }
}

我的假客户类:

package ru.rcitsakha.bitrixapi.client;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestParam;
import ru.rcitsakha.bitrixapi.config.FeignClientConfig;

@FeignClient(name = "odataClient", url = "${odata.url}", configuration = FeignClientConfig.class)
public interface OdataClient {

    // other endpoints with cirillic alphabet, but without whitespaces works fine

    // these endpoints with whitespaces doesn't work
    @GetMapping("/Document_СчетФактураВыданный")
    String getTaxInvoiceByContractId(
            @RequestHeader("Authorization") String token,
            @RequestParam("$format") String format,
            @RequestParam("$inlinecount") String inlineCount,
            @RequestParam("$filter") String contractId);
}

形成有问题的请求($filter)的我的存储库类

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Repository;
import ru.rcitsakha.bitrixapi.client.OdataClient;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

@Repository
@RequiredArgsConstructor
@Log4j2
public class OdataRepository {

    private final ObjectMapper mapper;
    private final OdataClient odataClient;

    @Value("${odata.responseFormat}")
    private String responseFormat;
    @Value("${odata.inlineCount}")
    private String inlineCount;
    @Value("${odata.auth_token}")
    private String token;

    public JsonNode getTaxInvoiceByContractId(String contractId) {
        JsonNode node = null;
        String filterRequest = "cast(Договор_Key,'Catalog_Договоры') eq guid'" + contractId + "'";
        String responseData = odataClient.getTaxInvoiceByContractId(token, responseFormat, inlineCount, filterRequest);
        try {
            node = mapper.readTree(responseData);
        } catch (JsonProcessingException e) {
            log.error("Object mapper could not read tree");
            e.printStackTrace();
        }

        return node;
    }
}

附: 建议,这对我没有帮助:

  1. URLEncoder.encode
  2. 将所有“”替换为“%20”
  3. 用“%20”替换所有“”的请求拦截器
  4. @QueryMap 而不是@RequestParam("$filter") String contractId
java spring-boot odata spring-cloud-feign
© www.soinside.com 2019 - 2024. All rights reserved.