PUT 请求使用邮递员工作但不使用 java、spring boot

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

我正在尝试在我的 Spring Boot 项目中进行 API 调用。 PUT 请求使用邮递员工作正常,我收到 204 状态代码(无内容)。而 JAVA 代码抛出 500 内部服务器错误 。 从代码生成的 URL(根据日志)与 postman 中的类似。 这是部分代码:

private void subscribe() {            
    String url = "https://api.linkedin.com/rest/eventSubscriptions/(developerApplication:urn%3Ali%3AdeveloperApplication%3A{dev_app_id},user:urn%3Ali%3Aperson%3A{person_id},entity:urn%3Ali%3Aorganization%3A{organization_id},eventType:ORGANIZATION_SOCIAL_ACTION_NOTIFICATIONS)";
    url.replace("{dev_app_id}", DEVELOPER_APPLICATION_ID);
    url.replace("{person_id}", "iTFpJkMpIl");
    url.replace("{organization_id}", ORGANIZATION_ID);

    // headers
    HttpHeaders httpHeaders = new HttpHeaders();
    httpHeaders.add("X-Restli-Protocol-Version", "2.0.0");
    httpHeaders.add("LinkedIn-Version", VERSION);
    httpHeaders.setContentType(MediaType.APPLICATION_JSON);
    httpHeaders.set(HttpHeaders.AUTHORIZATION, new StringBuilder("Bearer ").append(channel.getAccessToken()).toString());

    //body
    Webhook body = new Webhook(callback_url);
    HttpEntity<Webhook> entity = new HttpEntity<Webhook>(body, httpHeaders);
    logger.info("Hitting subscription API: {} with body: {}", url, getJson(entity.getBody()));
    logger.info("Headers: {}", entity.getHeaders().toSingleValueMap());
    try {
        restTemplate.put(url, entity);
    } catch (RestClientException e) {
        e.printStackTrace();
    }
}

// just to check logs
private String getJson(Webhook body) {
    try {
        return new ObjectMapper().writeValueAsString(body);
    } catch (Exception e) {
        logger.error("Error converting object to JSON.", e);
        return "";
    }
}

Webhook
班:

public class Webhook {
    private String webhook;

    public Webhook(String webhook) {
        this.webhook = webhook;
    }

    public String getWebhook() {
        return webhook;
    }

    public void setWebhook(String webhook) {
        this.webhook = webhook;
    }
}

这里的文档说明了需要生成的URL。特定 URN 已编码。

错误:

org.springframework.web.client.HttpServerErrorException$InternalServerError: 500 Server Error: "{"message":"Internal Server Error","status":500}"
        at org.springframework.web.client.HttpServerErrorException.create(HttpServerErrorException.java:102)
        at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:186)
        at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:137)
        at org.springframework.web.client.ResponseErrorHandler.handleError(ResponseErrorHandler.java:63)
        at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:942)
        at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:891)
        at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:790)
        at org.springframework.web.client.RestTemplate.put(RestTemplate.java:567)
        at com.germin8.main.services.EventSubscriber.lambda$0(EventSubscriber.java:152)
        at java.base/java.util.AbstractList$RandomAccessSpliterator.forEachRemaining(AbstractList.java:720)
        at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:762)
        at com.germin8.main.services.EventSubscriber.createSubscriptions(EventSubscriber.java:131)
        at com.germin8.main.services.EventSubscriber.organizarionSubscriptionMonitor(EventSubscriber.java:99)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:568)
        at org.springframework.scheduling.support.ScheduledMethodRunnable.runInternal(ScheduledMethodRunnable.java:130)
        at org.springframework.scheduling.support.ScheduledMethodRunnable.lambda$run$2(ScheduledMethodRunnable.java:124)
        at io.micrometer.observation.Observation.observe(Observation.java:499)
        at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:124)
        at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
        at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
        at java.base/java.util.concurrent.FutureTask.runAndReset(FutureTask.java:305)
        at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:305)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
        at java.base/java.lang.Thread.run(Thread.java:840)

这是我的pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.4</version>
        <relativePath/>
    </parent>
    <groupId>com.demo</groupId>
    <artifactId>linkedin-crawler</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>

    <name>linkedin-crawler</name>
    <description>Linkedin Crawling Service</description>
    <properties>
        <java.version>17</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-boot-starter</artifactId>
            <version>3.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
            <version>2.0.2</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>32.1.3-jre</version>
        </dependency>
    </dependencies>

    <repositories>
        <repository>
            <id>1_maven.apache.org</id>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
            <url>https://repo.maven.apache.org/maven2</url>
            <layout>default</layout>
        </repository>
        <repository>
          <id>jcenter-snapshots</id>
          <name>jcenter</name>
          <url>https://jcenter.bintray.com/</url>
        </repository>
    </repositories>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

我已经尝试过了

  1. 无需编码即可到达终点。
  2. 使用
    exchange
    代替
    put
restTemplate.exchange(url, HttpMethod.PUT, entity, String.class);

为了检查正文是否正确序列化,我向本地端点发出了类似的请求,它也是正确的。
为了检查标头,我记录了它们并将它们与我的邮递员请求中的标头进行比较。

java spring-boot rest linkedin-api
1个回答
0
投票

事实证明,在传递手动编码的 url 时,它会再次编码,从而导致双重编码。
然而,如果不执行编码,则 PUT 请求根本不会对其进行编码。 不知道出现这种情况的确切原因,但这是通过禁用默认编码来解决的解决方案。

DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory();
factory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.NONE);
restTemplate = new RestTemplateBuilder()
                  .uriTemplateHandler(factory)
                  .defaultHeader("X-Restli-Protocol-Version", "2.0.0")
                  .defaultHeader("LinkedIn-Version", VERSION)
                  .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
                  .build();
© www.soinside.com 2019 - 2024. All rights reserved.