X-Total-Count missing header error in React Admin with Spring Boot API

Viewed 541

I have my Spring Boot REST API. Link: "http://localhost:8080/api/components/component/list"

For the frontend, I am using React, above is the link that I want the "React Admin" app to consume.

Here is my Spring Boot's CORS Code, it is in a separate class called CorsConfig:

@Configuration
public class CorsConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry myCorsRegistry){
             myCorsRegistry.addMapping("/**")
            .allowedOrigins("http://localhost:3000")  //frontend's link
            .allowedHeaders("Access-Control-Allow-Origin","Access-Control-Allow-Header", "Access-Control-Expose-Headers", "Content-Range", "Content-Length", "Connection", "Content-Type", "X-Total-Count", "X-Content-Type-Options", "Set-Cookies", "*")
            .allowedMethods("GET", "POST", "PUT", "HEAD", "OPTIONS", "PATCH")
            .allowCredentials(true)
            
     }

}

For my controller class I have the following:

@CrossOrigin("http://localhost:3000")
@RequestMapping("/api/components/component")
@RestController
public class Component{
     @Autowired
     //code...
}

Here is my React Code:

import React from 'react';
import { Admin,ListGuesser, Resource} from 'react-admin';
import jsonServerProvider from "ra-data-json-server";

const parentURL = 
jsonServerProvider(`http://localhost:8080/api/components/component`);

function App() {
    return(
       <Admin dataProvider={parentURL}>
          <Resource name="list" list={ListGuesser} />
        </Admin>
    );
 }

Here is the error I am getting in my Chrome console:

The X-Total-Count header is missing in the HTTP Response. The jsonServer Data Provider expects 
responses for lists of resources to contain this header with the total number of results to build the 
pagination. If you are using CORS, did you declare X-Total-Count in the Access-Control-Expose-Headers 
header?

In my JavaScript code:

  1. When I use restProvider, I get the "Content-Range header is missing in the HTTP Response" error

  2. When I use jsonServerProvider, I get the "X-Total-Count header is missing in the HTTP Response" error

My Question: How to fix the above error?

2 Answers

In the RestController add crossorigin base on your client

@CrossOrigin(origins = {"http://localhost:3000"}, exposedHeaders = "X-Total-Count")

Create a new class ConrolAdvice to send response

@ControllerAdvice
public class ResourceSizeAdvice implements ResponseBodyAdvice<Collection<?>> {

    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        //Checks if this advice is applicable.
        //In this case it applies to any endpoint which returns a collection.
        return Collection.class.isAssignableFrom(returnType.getParameterType());
    }

    @Override
    public Collection<?> beforeBodyWrite(Collection<?> body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        response.getHeaders().add("X-Total-Count", String.valueOf(body.size()));
        return body;
    }
}

Looks like the header to be used now is:

e.g. Content-Range: posts 0-24/319

I'm reading the Table name from the entity to expose this:

                String tableName = page.getContent().get(0).getClass().getAnnotationsByType(Table.class)[0].name();
                long minElement = page.getNumber() * page.getSize();
                long maxElement = Math.min(minElement + page.getSize() - 1, page.getTotalElements() - 1);
                long totalElements = page.getTotalElements();
                String contentRange = String.format("%s %d-%d/%d", tableName, minElement, maxElement, totalElements);
                
                response.getHeaders().add("Content-Range", contentRange);

On top of the Annotation for CORS mentioned above:

@CrossOrigin(origins = {"http://localhost:3000"}, exposedHeaders = "Content-Range")
Related