errors) {
    return Optional.ofNullable(errors.get("message"))
        .orElseGet(() -> errors.getOrDefault("error", "Internal Server Error"));
  }
}
```
返回格式(例子):
```json
{
    "code": 504,
    "message": "Gateway Timeout",
    "data": null,
    "success": false
}
```
#### 方法2-继承`DefaultErrorAttributes`
使用此方法,webflux环境中自己重写返回的`errorAttributes`需要有`status`,否则报空指针异常,servlet环境中没有这种情况发生。
```java
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler;
import org.springframework.boot.web.error.ErrorAttributeOptions;
import org.springframework.boot.web.reactive.error.DefaultErrorAttributes;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.server.ServerRequest;
/**
 * Customize error response data.
 *
 * @author lzhpo
 */
@Component
public class GatewayErrorAttributes extends DefaultErrorAttributes {
  /**
   * Notes: errorAttributes must containsKey "status", otherwise, will throw NullPointerException
   *
   * {@code
   * 	protected Mono renderErrorResponse(ServerRequest request) {
   * 		Map error = getErrorAttributes(request, getErrorAttributeOptions(request, MediaType.ALL));
   * 		return ServerResponse.status(getHttpStatus(error)).contentType(MediaType.APPLICATION_JSON)
   * 				.body(BodyInserters.fromValue(error));
   *  }
   *
   * 	protected int getHttpStatus(Map errorAttributes) {
   * 		return (int) errorAttributes.get("status");
   *  }
   * }
   *
   * @see DefaultErrorWebExceptionHandler#renderErrorResponse
   * @see DefaultErrorWebExceptionHandler#getHttpStatus
   * @param request the source request
   * @param options options for error attribute contents
   * @return error attributes
   */
  @Override
  public Map getErrorAttributes(
      ServerRequest request, ErrorAttributeOptions options) {
    Map errors = super.getErrorAttributes(request, options);
    Map errorAttributes = new HashMap<>(4);
    errorAttributes.put("success", false);
    errorAttributes.put("status", errors.getOrDefault("status", 500));
    errorAttributes.put("message", getErrorMessage(errors));
    errorAttributes.put("data", null);
    return errorAttributes;
  }
  /**
   * Get an error message.
   *
   * @param errors error attributes
   * @return error message
   */
  private Object getErrorMessage(Map errors) {
    return Optional.ofNullable(errors.get("message"))
        .orElseGet(() -> errors.getOrDefault("error", "Internal Server Error"));
  }
}
```
详情可见:
```java
// org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler#renderErrorResponse
protected Mono renderErrorResponse(ServerRequest request) {
    Map error = getErrorAttributes(request, getErrorAttributeOptions(request, MediaType.ALL));
    return ServerResponse.status(getHttpStatus(error)).contentType(MediaType.APPLICATION_JSON)
        .body(BodyInserters.fromValue(error));
}
// org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler#getHttpStatus
protected int getHttpStatus(Map errorAttributes) {
    return (int) errorAttributes.get("status");
}
```
返回格式(例子):
```json
{
    "status": 504,
    "message": "Gateway Timeout",
    "data": null,
    "success": false
}
```
## Actuator端点API
如果我们想对网关做一些事情,我们需要暴露`gateway`端点。
```java
management:
  endpoints:
    web:
      exposure:
        include: gateway
```
### 1.获取所有路由配置
```js
GET /actuator/gateway/routes
```
### 2.根据路由ID获取路由配置
```js
GET /actuator/gateway/routes/${routeId}
```
### 3.获取所有路由谓词类名
```js
GET /actuator/gateway/routes/predicates
```
### 4.根据路由ID获取路由谓词类名
```js
GET /actuator/gateway/routes/${routeId}/predicates
```
### 5.获取所有路由过滤器类名
```js
GET /actuator/gateway/routes/filters
```
### 6.根据路由ID获取路由过滤器类名
```js
GET /actuator/gateway/routes/${routeId}/filters
```
### 7.获取所有全局过滤器类名
```js
GET /actuator/gateway/routes/global-filters
```
### 8.刷新路由
```js
POST /actuator/gateway/routes/refresh
```