/** * Change the response code for this response. If not specified, the code will be a {@code 200}. * Setting the response code after the response headers have been transmitted has no effect. * * @param responseCode the new code * @throws IllegalStateException if a response or upgrade was already sent */ public void setResponseCode(final int responseCode) { if (responseCode < 0 || responseCode > 999) { throw new IllegalArgumentException("Invalid response code"); } int oldVal, newVal; do { oldVal = state; if (allAreSet(oldVal, FLAG_RESPONSE_SENT)) { throw UndertowMessages.MESSAGES.responseAlreadyStarted(); } newVal = oldVal & ~MASK_RESPONSE_CODE | responseCode & MASK_RESPONSE_CODE; } while (!stateUpdater.compareAndSet(this, oldVal, newVal)); }
/** * Transmit the response headers. After this method successfully returns, the response channel may * become writable. * * <p>If this method fails the request and response channels will be closed. * * <p>This method runs asynchronously. If the channel is writable it will attempt to write as much * of the response header as possible, and then queue the rest in a listener and return. * * <p>If future handlers in the chain attempt to write before this is finished XNIO will just * magically sort it out so it works. This is not actually implemented yet, so we just terminate * the connection straight away at the moment. * * <p>TODO: make this work properly * * @throws IllegalStateException if the response headers were already sent */ void startResponse() throws IllegalStateException { int oldVal, newVal; do { oldVal = state; if (allAreSet(oldVal, FLAG_RESPONSE_SENT)) { throw UndertowMessages.MESSAGES.responseAlreadyStarted(); } newVal = oldVal | FLAG_RESPONSE_SENT; } while (!stateUpdater.compareAndSet(this, oldVal, newVal)); log.tracef( "Starting to write response for %s using channel %s", this, underlyingResponseChannel); final HeaderMap responseHeaders = this.responseHeaders; responseHeaders.lock(); }