/** * Parses the specified HTTP status line into a {@link HttpResponseStatus}. The expected formats of the line are: * <ul> * <li>{@code statusCode} (e.g. 200)</li> * <li>{@code statusCode} {@code reasonPhrase} (e.g. 404 Not Found)</li> * </ul> * * @throws IllegalArgumentException if the specified status line is malformed */ public static HttpResponseStatus parseLine(CharSequence line) { return (line instanceof AsciiString) ? parseLine((AsciiString) line) : parseLine(line.toString()); }
/** * Apply HTTP/2 rules while translating status code to {@link HttpResponseStatus} * * @param status The status from an HTTP/2 frame * @return The HTTP/1.x status * @throws Http2Exception If there is a problem translating from HTTP/2 to HTTP/1.x */ public static HttpResponseStatus parseStatus(CharSequence status) throws Http2Exception { HttpResponseStatus result; try { result = parseLine(status); if (result == HttpResponseStatus.SWITCHING_PROTOCOLS) { throw connectionError(PROTOCOL_ERROR, "Invalid HTTP/2 status code '%d'", result.code()); } } catch (Http2Exception e) { throw e; } catch (Throwable t) { throw connectionError(PROTOCOL_ERROR, t, "Unrecognized HTTP status code '%s' encountered in translation to HTTP/1.x", status); } return result; }
HttpResponseStatus status = HttpResponseStatus.parseLine(headers.get(STATUS)); HttpVersion version = HttpVersion.valueOf(headers.getAsString(VERSION)); headers.remove(STATUS);
private void handleEndOfStream(final ChannelHandlerContext context, final Http2Stream stream, final Http2Headers headers, final ByteBuf data) { final PushNotificationPromise<ApnsPushNotification, PushNotificationResponse<ApnsPushNotification>> responsePromise = stream.getProperty(this.responsePromisePropertyKey); final ApnsPushNotification pushNotification = responsePromise.getPushNotification(); final HttpResponseStatus status = HttpResponseStatus.parseLine(headers.status()); if (HttpResponseStatus.OK.equals(status)) { responsePromise.trySuccess(new SimplePushNotificationResponse<>(responsePromise.getPushNotification(), true, getApnsIdFromHeaders(headers), null, null)); } else { if (data != null) { final ErrorResponse errorResponse = GSON.fromJson(data.toString(StandardCharsets.UTF_8), ErrorResponse.class); this.handleErrorResponse(context, stream.id(), headers, pushNotification, errorResponse); } else { log.warn("Gateway sent an end-of-stream HEADERS frame for an unsuccessful notification."); } } }
protected void handleErrorResponse(final ChannelHandlerContext context, final int streamId, final Http2Headers headers, final ApnsPushNotification pushNotification, final ErrorResponse errorResponse) { final PushNotificationPromise<ApnsPushNotification, PushNotificationResponse<ApnsPushNotification>> responsePromise = this.connection().stream(streamId).getProperty(this.responsePromisePropertyKey); final HttpResponseStatus status = HttpResponseStatus.parseLine(headers.status()); responsePromise.trySuccess(new SimplePushNotificationResponse<>(responsePromise.getPushNotification(), HttpResponseStatus.OK.equals(status), getApnsIdFromHeaders(headers), errorResponse.getReason(), errorResponse.getTimestamp())); }
/** * Parses the specified HTTP status line into a {@link HttpResponseStatus}. The expected formats of the line are: * <ul> * <li>{@code statusCode} (e.g. 200)</li> * <li>{@code statusCode} {@code reasonPhrase} (e.g. 404 Not Found)</li> * </ul> * * @throws IllegalArgumentException if the specified status line is malformed */ public static HttpResponseStatus parseLine(CharSequence line) { return (line instanceof AsciiString) ? parseLine((AsciiString) line) : parseLine(line.toString()); }
/** * Parses the specified HTTP status line into a {@link HttpResponseStatus}. The expected formats of the line are: * <ul> * <li>{@code statusCode} (e.g. 200)</li> * <li>{@code statusCode} {@code reasonPhrase} (e.g. 404 Not Found)</li> * </ul> * * @throws IllegalArgumentException if the specified status line is malformed */ public static HttpResponseStatus parseLine(CharSequence line) { return (line instanceof AsciiString) ? parseLine((AsciiString) line) : parseLine(line.toString()); }
/** * Parses the specified HTTP status line into a {@link HttpResponseStatus}. The expected formats of the line are: * <ul> * <li>{@code statusCode} (e.g. 200)</li> * <li>{@code statusCode} {@code reasonPhrase} (e.g. 404 Not Found)</li> * </ul> * * @throws IllegalArgumentException if the specified status line is malformed */ public static HttpResponseStatus parseLine(CharSequence line) { return (line instanceof AsciiString) ? parseLine((AsciiString) line) : parseLine(line.toString()); }
/** * Parses the specified HTTP status line into a {@link HttpResponseStatus}. The expected formats of the line are: * <ul> * <li>{@code statusCode} (e.g. 200)</li> * <li>{@code statusCode} {@code reasonPhrase} (e.g. 404 Not Found)</li> * </ul> * * @throws IllegalArgumentException if the specified status line is malformed */ public static HttpResponseStatus parseLine(CharSequence line) { return (line instanceof AsciiString) ? parseLine((AsciiString) line) : parseLine(line.toString()); }
@Override public void sendError(int sc, String msg) throws IOException { this.httpResponse.setStatus(HttpResponseStatus.parseLine(String.valueOf(sc) + " " + msg)); } @Override
public HttpResponseStatus getStatus() { return HttpResponseStatus.parseLine(headers.status()); }
/** * Apply HTTP/2 rules while translating status code to {@link HttpResponseStatus} * * @param status The status from an HTTP/2 frame * @return The HTTP/1.x status * @throws Http2Exception If there is a problem translating from HTTP/2 to HTTP/1.x */ public static HttpResponseStatus parseStatus(CharSequence status) throws Http2Exception { HttpResponseStatus result; try { result = parseLine(status); if (result == HttpResponseStatus.SWITCHING_PROTOCOLS) { throw connectionError(PROTOCOL_ERROR, "Invalid HTTP/2 status code '%d'", result.code()); } } catch (Http2Exception e) { throw e; } catch (Throwable t) { throw connectionError(PROTOCOL_ERROR, t, "Unrecognized HTTP status code '%s' encountered in translation to HTTP/1.x", status); } return result; }
/** * Apply HTTP/2 rules while translating status code to {@link HttpResponseStatus} * * @param status The status from an HTTP/2 frame * @return The HTTP/1.x status * @throws Http2Exception If there is a problem translating from HTTP/2 to HTTP/1.x */ public static HttpResponseStatus parseStatus(CharSequence status) throws Http2Exception { HttpResponseStatus result; try { result = parseLine(status); if (result == HttpResponseStatus.SWITCHING_PROTOCOLS) { throw connectionError(PROTOCOL_ERROR, "Invalid HTTP/2 status code '%d'", result.code()); } } catch (Http2Exception e) { throw e; } catch (Throwable t) { throw connectionError(PROTOCOL_ERROR, t, "Unrecognized HTTP status code '%s' encountered in translation to HTTP/1.x", status); } return result; }
@Override public void onHeadersRead(final ChannelHandlerContext context, final int streamId, final Http2Headers headers, final int padding, final boolean endOfStream) throws Http2Exception { log.trace("Received headers from APNs gateway on stream {}: {}", streamId, headers); if (endOfStream) { final HttpResponseStatus status = HttpResponseStatus.parseLine(headers.status()); final boolean success = HttpResponseStatus.OK.equals(status); if (!success) { log.warn("Gateway sent an end-of-stream HEADERS frame for an unsuccessful notification."); } final ApnsPushNotification pushNotification = ApnsClientHandler.this.pushNotificationsByStreamId.remove(streamId); ApnsClientHandler.this.authenticationTokensByStreamId.remove(streamId); if (HttpResponseStatus.INTERNAL_SERVER_ERROR.equals(status)) { ApnsClientHandler.this.apnsClient.handleServerError(pushNotification, null); } else { ApnsClientHandler.this.apnsClient.handlePushNotificationResponse( new SimplePushNotificationResponse<>(pushNotification, success, null, null)); } } else { ApnsClientHandler.this.headersByStreamId.put(streamId, headers); } }
HttpResponseStatus status = HttpResponseStatus.parseLine(headers.get(STATUS)); HttpVersion version = HttpVersion.valueOf(headers.getAsString(VERSION)); headers.remove(STATUS);
HttpResponseStatus status = HttpResponseStatus.parseLine(headers.get(STATUS)); HttpVersion version = HttpVersion.valueOf(headers.getAsString(VERSION)); headers.remove(STATUS);
HttpResponseStatus status = HttpResponseStatus.parseLine(headers.get(STATUS)); HttpVersion version = HttpVersion.valueOf(headers.getAsString(VERSION)); headers.remove(STATUS);
@Override public int onDataRead(final ChannelHandlerContext context, final int streamId, final ByteBuf data, final int padding, final boolean endOfStream) throws Http2Exception { log.trace("Received data from APNs gateway on stream {}: {}", streamId, data.toString(StandardCharsets.UTF_8)); final int bytesProcessed = data.readableBytes() + padding; if (endOfStream) { final Http2Headers headers = ApnsClientHandler.this.headersByStreamId.remove(streamId); final String authenticationToken = ApnsClientHandler.this.authenticationTokensByStreamId.remove(streamId); final ApnsPushNotification pushNotification = ApnsClientHandler.this.pushNotificationsByStreamId.remove(streamId); final HttpResponseStatus status = HttpResponseStatus.parseLine(headers.status()); final String responseBody = data.toString(StandardCharsets.UTF_8); if (HttpResponseStatus.INTERNAL_SERVER_ERROR.equals(status)) { ApnsClientHandler.this.apnsClient.handleServerError(pushNotification, responseBody); } else { final ErrorResponse errorResponse = gson.fromJson(responseBody, ErrorResponse.class); if (ApnsClient.EXPIRED_AUTH_TOKEN_REASON.equals(errorResponse.getReason())) { try { ApnsClientHandler.this.apnsClient.getAuthenticationTokenSupplierForTopic(pushNotification.getTopic()).invalidateToken(authenticationToken); } catch (final NoKeyForTopicException e) { // This should only happen if somebody de-registered the topic after a notification was sent log.warn("Authentication token expired, but no key registered for topic {}", pushNotification.getTopic()); } } ApnsClientHandler.this.apnsClient.handlePushNotificationResponse( new SimplePushNotificationResponse<>(pushNotification, HttpResponseStatus.OK.equals(status), errorResponse.getReason(), errorResponse.getTimestamp())); } } else { log.error("Gateway sent a DATA frame that was not the end of a stream."); } return bytesProcessed; }
private void handleEndOfStream(final ChannelHandlerContext context, final Http2Stream stream, final Http2Headers headers, final ByteBuf data) { final PushNotificationPromise<ApnsPushNotification, PushNotificationResponse<ApnsPushNotification>> responsePromise = stream.getProperty(this.responsePromisePropertyKey); final ApnsPushNotification pushNotification = responsePromise.getPushNotification(); final HttpResponseStatus status = HttpResponseStatus.parseLine(headers.status()); if (HttpResponseStatus.OK.equals(status)) { responsePromise.trySuccess(new SimplePushNotificationResponse<>(responsePromise.getPushNotification(), true, getApnsIdFromHeaders(headers), null, null)); } else { if (data != null) { final ErrorResponse errorResponse = GSON.fromJson(data.toString(StandardCharsets.UTF_8), ErrorResponse.class); this.handleErrorResponse(context, stream.id(), headers, pushNotification, errorResponse); } else { log.warn("Gateway sent an end-of-stream HEADERS frame for an unsuccessful notification."); } } }
protected void handleErrorResponse(final ChannelHandlerContext context, final int streamId, final Http2Headers headers, final ApnsPushNotification pushNotification, final ErrorResponse errorResponse) { final PushNotificationPromise<ApnsPushNotification, PushNotificationResponse<ApnsPushNotification>> responsePromise = this.connection().stream(streamId).getProperty(this.responsePromisePropertyKey); final HttpResponseStatus status = HttpResponseStatus.parseLine(headers.status()); responsePromise.trySuccess(new SimplePushNotificationResponse<>(responsePromise.getPushNotification(), HttpResponseStatus.OK.equals(status), getApnsIdFromHeaders(headers), errorResponse.getReason(), errorResponse.getTimestamp())); }