@Override public synchronized Resp response() { if (response == null) { response = new RespImpl(this); if (defaultContentType != null) { response.contentType(defaultContentType); } } return response; }
private String validateResponse() { if (response == null) { return "Response wasn't provided!"; } if (response.result() == null && response.body() == null && response.redirect() == null && response.file() == null && response.raw() == null && !response().mvc()) { return "Response content wasn't provided!"; } if (response.contentType() == null && response.raw() == null) { return "Response content type wasn't provided!"; } return null; }
@Override public OutputStream out() { if (chunked == null) { synchronized (this) { if (chunked == null) { checkStreamingPreconditions(); // the chunked response object, which buffers the response data chunked = new ChunkedResponse(this); // set the header early, so it can be overwritten by the app, if necessary header("Transfer-Encoding", "chunked"); } } } return chunked; }
private void saveToCache() { U.must(posBeforeBody != UNDEFINED); Buf out = channel.output(); int posAfterBody = out.size(); int bodyLength = (int) (posAfterBody - posBeforeBody); // FIXME validate '\r\n\r\n' before the start position of the response body Cache<HTTPCacheKey, CachedResp> cache = route.cache(); U.notNull(cache, "route.cache"); SimpleHttpResp proxyResp = new SimpleHttpResp(); proxyResp.cookies = U.map(U.safe(response != null ? response.cookies() : null)); Map<String, String> headers = response != null ? response.headers() : Collections.emptyMap(); HttpUtils.proxyResponseHeaders(headers, proxyResp); proxyResp.code = response != null ? response.code() : 200; if (proxyResp.contentType == null) { proxyResp.contentType = response != null ? response.contentType() : defaultContentType; } // don't cache the response if it contains cookies or token data if (U.notEmpty(proxyResp.cookies) || hasToken()) return; ByteBuffer body = writeBodyToBuf(out, bodyLength); CachedResp cached = new CachedResp(proxyResp.code, proxyResp.contentType, proxyResp.headers, body); cache.set(cacheKey, cached); }
@Override public synchronized Resp body(ByteBuffer body) { ensureCanChange(); this.body = body; return this; }
private void checkStreamingPreconditions() { U.must(result() == null, "The response result has already been set, so cannot write the response through OutputStream, too!"); U.must(body() == null, "The response body has already been set, so cannot write the response through OutputStream, too!"); U.must(raw() == null, "The raw response has already been set, so cannot write the response through OutputStream, too!"); }
private static RespBody createRespBodyFromResult(Req req, RespImpl resp) { Object result = resp.result(); Object body = resp.body(); if (result instanceof RespBody) { return (RespBody) result; } else if (body instanceof RespBody) { return (RespBody) body; } else if (resp.mvc()) { byte[] bytes = ResponseRenderer.renderMvc((ReqImpl) req, resp); HttpUtils.postProcessResponse(resp); // the response might have been changed, so post-process again return new RespBodyBytes(bytes); } else if (body != null) { return new RespBodyBytes(Msc.toBytes(body)); } else if (result != null) { return resultToRespBody(resp, result); } else { throw U.rte("There's nothing to render!"); } }
@Override public MediaType contentType() { MediaType contentType = response != null ? response.contentType() : null; return U.or(contentType, defaultContentType); }
@Override public Resp cookie(String name, String value, String... extras) { if (U.notEmpty(extras)) { value += "; " + U.join("; ", extras); } if (!cookieContainsPath(extras)) { value += "; path=" + HttpUtils.cookiePath(); } cookies().put(name, value); return this; }
private void renderResponse(int code, MediaType contentType, RespBody body) { rendering = true; completed = body != null; HttpIO.INSTANCE.respond( HttpUtils.maybe(this), channel, connId, handle, code, isKeepAlive, contentType, body, response != null ? response.headers() : null, response != null ? response.cookies() : null ); }
@Override public synchronized void flush() { // lazy init if (startChunkedResp.go()) resp.startChunkedOutputStream(); // the chunk must not be empty (empty chunk terminates the HTTP response) if (chunk.size() > 0) { resp.chunk(chunk.array(), 0, chunk.size()); chunk.reset(); } }
private void renderResponse() { HttpUtils.postProcessResponse(response); if (response.raw() != null) { int posBeforeResponse = channel.output().size(); byte[] bytes = Msc.toBytes(response.raw()); channel.write(bytes); if (willSaveToCache()) posBeforeBody = posBeforeResponse + HttpUtils.findBodyStart(bytes); completed = true; HttpIO.INSTANCE.done(this); } else { // render the response body RespBody body = BodyRenderer.toRespBody(this, response); // render the response doRendering(response.code(), body); } }
@Override public Screen screen() { if (screen == null) { synchronized (this) { if (screen == null) { screen = createScreen(); } } } return screen; }
void startChunkedOutputStream() { req.doRendering(code(), null); }
private void saveToCache() { U.must(posBeforeBody != UNDEFINED); Buf out = channel.output(); int posAfterBody = out.size(); int bodyLength = (int) (posAfterBody - posBeforeBody); // FIXME validate '\r\n\r\n' before the start position of the response body Cache<HTTPCacheKey, CachedResp> cache = route.cache(); U.notNull(cache, "route.cache"); SimpleHttpResp proxyResp = new SimpleHttpResp(); proxyResp.cookies = U.map(U.safe(response != null ? response.cookies() : null)); Map<String, String> headers = response != null ? response.headers() : Collections.<String, String>emptyMap(); HttpUtils.proxyResponseHeaders(headers, proxyResp); proxyResp.code = response != null ? response.code() : 200; if (proxyResp.contentType == null) { proxyResp.contentType = response != null ? response.contentType() : defaultContentType; } // don't cache the response if it contains cookies or token data if (U.notEmpty(proxyResp.cookies) || hasToken()) return; ByteBuffer body = writeBodyToBuf(out, bodyLength); CachedResp cached = new CachedResp(proxyResp.code, proxyResp.contentType, proxyResp.headers, body); cache.set(cacheKey, cached); }
@Override public synchronized Resp raw(byte[] raw) { ensureCanChange(); this.raw = raw; return this; }
private void checkStreamingPreconditions() { U.must(result() == null, "The response result has already been set, so cannot write the response through OutputStream, too!"); U.must(body() == null, "The response body has already been set, so cannot write the response through OutputStream, too!"); U.must(raw() == null, "The raw response has already been set, so cannot write the response through OutputStream, too!"); }
private static RespBody createRespBodyFromResult(Req req, RespImpl resp) { Object result = resp.result(); Object body = resp.body(); if (result instanceof RespBody) { return (RespBody) result; } else if (body instanceof RespBody) { return (RespBody) body; } else if (resp.mvc()) { byte[] bytes = ResponseRenderer.renderMvc((ReqImpl) req, resp); HttpUtils.postProcessResponse(resp); // the response might have been changed, so post-process again return new RespBodyBytes(bytes); } else if (body != null) { return new RespBodyBytes(Msc.toBytes(body)); } else if (result != null) { return resultToRespBody(resp, result); } else { throw U.rte("There's nothing to render!"); } }
@Override public Resp html(Object content) { return contentType(MediaType.HTML_UTF_8).result(content); }