我创建了一个具有“Spring web”依赖项的新 Spring boot 应用程序。该模板使用Spring boot 3.2.5版本。相关依赖项是:
<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>
</dependencies>
创建休息控制器后,我在 Dart / Flutter 客户端中收到 Error: ClientException: XMLHttpRequest error.。在浏览器中访问 URL 工作正常并返回 JSON。
阅读完问题后,我认为服务器配置中缺少 Access-Control-Allow-Origin 标头。
我尝试将其添加到控制器中:
package com.vogella.spring.jsonserver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.vogella.spring.jsonserver.controller.TutorialCategoryProvider;
import com.vogella.spring.jsonserver.model.TutorialCategory;
import com.vogella.spring.jsonserver.model.TutorialLink;
import java.util.List;
@RestController
@CrossOrigin(origins = "*")
public class CategoryController {
private final TutorialCategoryProvider provider;
@Autowired
public CategoryController(TutorialCategoryProvider yourService) {
this.provider = yourService;
}
@CrossOrigin(origins = "*")
@GetMapping("/categories")
public List<TutorialCategory> get() {
// Your implementation to fetch all links from your data source
// For example, from a database or a service
return provider.getTutorialCategories();
}
}
还尝试将其添加到应用程序的配置中:
package com.vogella.spring.jsonserver;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@SpringBootApplication
public class RestServiceApplication {
public static void main(String[] args) {
SpringApplication.run(RestServiceApplication.class, args);
}
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
System.out.println("Called");
registry.addMapping("/**")
.allowedOrigins("*")
.maxAge(4800)
.allowCredentials(false)
.allowedMethods("POST", "GET", "OPTIONS", "DELETE", "PUT")
.allowedHeaders("origin", "Content-Type", "X-Requested-With", "X-File-Name", "x-mime-type",
"Accept-Encoding", "Authorization", "Content-Range", "Content-Disposition",
"Content-Description", "Access-Control-Request-Method", "Access-Control-Request-Headers");
}
};
}
}
但是如果我通过curl 检查此标头,我看不到它:
curl -I http://localhost:8080/categories
HTTP/1.1 200
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json
Transfer-Encoding: chunked
Date: Thu, 25 Apr 2024 11:37:39 GMT
有什么我错过的建议吗?
您找错地方了。
浏览器在实际请求之前发送
OPTIONS
请求以获取有关被调用端点的一些信息。响应标头 Access-Control-Allow-Origin
由 OPTIONS
请求返回,而不是由以下 GET
请求返回。浏览器预先发送的 OPTIONS
请求也可以用curl复制:
curl --verbose --request OPTIONS "[endpoint being called]" --header "Origin: [host from which the endpoint is being called]" --header "Access-Control-Request-Method: [http method with which the endpoint is being called]"
因此,在您的情况下,命令行如下所示(我假设 Spring Boot 应用程序为前端和 API 提供服务):
curl --verbose --request OPTIONS "http://localhost:8080/categories" --header "Origin: localhost:8080" --header "Access-Control-Request-Method: GET"
我已经根据您的示例设置了一个小型演示应用程序,curl 命令给出了以下输出:
* Trying [::1]:8080...
* Connected to localhost (::1) port 8080
> OPTIONS /categories HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/8.4.0
> Accept: */*
> Origin: localhost:8080
> Access-Control-Request-Method: GET
>
< HTTP/1.1 200
< Vary: Origin
< Vary: Access-Control-Request-Method
< Vary: Access-Control-Request-Headers
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Methods: POST,GET,OPTIONS,DELETE,PUT
< Access-Control-Max-Age: 4800
< Allow: GET, HEAD, POST, PUT, DELETE, OPTIONS, PATCH
< Content-Length: 0
< Date: Thu, 25 Apr 2024 21:27:40 GMT
<
* Connection #0 to host localhost left intact
请记住,如果您为 API 添加安全性,即一旦您的 API 需要凭据进行身份验证,
Access-Control-Allow-Origin
标头将不再允许使用通配符,并且您必须显式指定所有可能的引用主机名。