错误处理与graphql-java-tools和graphql-spring-boot-starter

huangapple go评论76阅读模式
英文:

Error handling with graphql-java-tools and graphql-spring-boot-starter

问题

@Component
public class CustomGraphQLErrorHandler implements GraphQLErrorHandler {

    @Override
    public List<GraphQLError> processErrors(List<GraphQLError> list) {
        return list.stream().map(this::getNested).collect(Collectors.toList());
    }

    private GraphQLError getNested(GraphQLError error) {
        if (error instanceof ExceptionWhileDataFetching) {
            ExceptionWhileDataFetching exceptionError = (ExceptionWhileDataFetching) error;
            if (exceptionError.getException() instanceof GraphQLError) {
                return (GraphQLError) exceptionError.getException();
            }
        }
        return error;
    }
}
英文:

How to handle errors in my graphQL API? I am using graphql-java-tools and graphql-spring-boot-starter. I created error handler but every time I get response 200 even when exception was thrown. Could you tell me how I should set error code e.g 400 in response?

@Component
public class CustomGraphQLErrorHandler implements GraphQLErrorHandler {

    @Override
    public List&lt;GraphQLError&gt; processErrors(List&lt;GraphQLError&gt; list) {
        return list.stream().map(this::getNested).collect(Collectors.toList());
    }

    private GraphQLError getNested(GraphQLError error) {
        if (error instanceof ExceptionWhileDataFetching) {
            ExceptionWhileDataFetching exceptionError = (ExceptionWhileDataFetching) error;
            if (exceptionError.getException() instanceof GraphQLError) {
                return (GraphQLError) exceptionError.getException();
            }
        }
        return error;
    }
}

答案1

得分: 5

GraphQL服务器在能够接受请求时返回HTTP 200状态码(语法有效,服务器运行正常...)。

如果发生错误,它会返回状态码200,并在响应中填充错误列表。

因此,在客户端,您将会有:

  • 如果HTTP状态码与200不同,则会出现技术服务器错误。
  • 如果HTTP状态码为200且错误列表不为空,则处理请求时会出现错误(无论是技术错误还是其他错误)。
  • 如果HTTP状态码为200且错误列表不存在,则不会出现错误(根据GraphQL规范,不应该存在且为空)。
英文:

The GraphQL server returns an HTTP 200 when it can accept the request (the syntax is valid, the server is up...).

If an error occurs, it returns an 200 and fills the errors list in the response.

So, on client side, you will have:

  • Technical server errors, if the HTTP status is different from 200
  • Errors when handling the request (technical or not) if the HTTP
    status is 200 and the errors list is not empty
  • No error if the HTTP
    status is 200 and the errors list is not present (it should not be
    present and empty, according to the GraphQL spec)

答案2

得分: 2

你可以尝试在错误处理方法中抛出一些异常,例如:

package my.company.graphql.error;

import java.util.List;
import java.util.stream.Collectors;

import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ResponseStatusException;

import graphql.GraphQLError;
import graphql.GraphQLException;
import graphql.servlet.core.GraphQLErrorHandler;
import graphql.validation.ValidationError;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component
public class GraphQLErrorHandlerImpl implements GraphQLErrorHandler {

    @Override
    public List<GraphQLError> processErrors(List<GraphQLError> graphQLErrors) {
        return graphQLErrors.stream().map(this::handleGraphQLError).collect(Collectors.toList());
    }

    private GraphQLError handleGraphQLError(GraphQLError error) {
        if (error instanceof GraphQLException) {
            throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "GraphQLException as GraphQLError...", (GraphQLException) error);
        } else if (error instanceof ValidationError){
            throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "ValidationError: " + error.getMessage());
        } else {
            log.error("Yet another GraphQLError...", error);
            return error;
        }
    }

}

...但是在响应中,你只会得到400状态码,没有其他更多的信息,因为Spring不会处理抛出的异常,你是在与GraphQL servlet交互,而不是Spring servlet,例如:http://127.0.0.1:8080/graphql

只有在日志中,你才能看到堆栈跟踪(这只是一个示例,显示了GraphQL查询中未使用的片段的验证错误):

[2020-09-23 15:59:34.382]-[080-exec-2]-[INFO ]-[g.s.AbstractGraphQLHttpServlet]: Bad POST request: parsing failed
org.springframework.web.server.ResponseStatusException: 400 BAD_REQUEST "ValidationError: Validation error of type UnusedFragment: Unused fragment someUnusedFragment"
    at my.company.graphql.error.GraphQLErrorHandlerImpl.handleGraphQLError(GraphQLErrorHandlerImpl.java:33) ~[classes/:na]

你可以根据需要引入更复杂的GraphQL错误处理,但这只会是测试和尝试的过程(就像我们过去做的一样...)

英文:

You can try to throw some exceptions in your error handling method e.g.

package my.company.graphql.error;

import java.util.List;
import java.util.stream.Collectors;

import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ResponseStatusException;

import graphql.GraphQLError;
import graphql.GraphQLException;
import graphql.servlet.core.GraphQLErrorHandler;
import graphql.validation.ValidationError;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component
public class GraphQLErrorHandlerImpl implements GraphQLErrorHandler {

	@Override
	public List&lt;GraphQLError&gt; processErrors(List&lt;GraphQLError&gt; graphQLErrors) {
		return graphQLErrors.stream().map(this::handleGraphQLError).collect(Collectors.toList());
	}

	private GraphQLError handleGraphQLError(GraphQLError error) {
		if (error instanceof GraphQLException) {
			throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, &quot;GraphQLException as GraphQLError...&quot;, (GraphQLException) error);
		} else if (error instanceof ValidationError){
			throw new ResponseStatusException(HttpStatus.BAD_REQUEST, &quot;ValidationError: &quot; + error.getMessage());
		} else {
			log.error(&quot;Yet another GraphQLError...&quot;, error);
			return error;
		}
	}

}

...except you'll only get the 400 status code and nothing more in your response because Spring is not here to handle the thrown exceptions as you're talking with the GraphQL servlet (not the Spring one) at e.g. http://127.0.0.1:8080/graphql

Only in your log you should be able to see the stacktrace: (this is just an example with a validation error for an unused fragment in the GraphQL query)

[2020-09-23 15:59:34.382]-[080-exec-2]-[INFO ]-[g.s.AbstractGraphQLHttpServlet]: Bad POST request: parsing failed
org.springframework.web.server.ResponseStatusException: 400 BAD_REQUEST &quot;ValidationError: Validation error of type UnusedFragment: Unused fragment someUnusedFragment&quot;
	at my.company.graphql.error.GraphQLErrorHandlerImpl.handleGraphQLError(GraphQLErrorHandlerImpl.java:33) ~[classes/:na]

It's up to you to introduce a more complex handling of GraphQL errors, but that'll just be test & trial (as we've also done for quite some time...)

huangapple
  • 本文由 发表于 2020年5月29日 19:34:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/62085033.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定