Skip to content

Commit

Permalink
Refactored HTTP components.
Browse files Browse the repository at this point in the history
  • Loading branch information
nmihajlovski committed Jan 2, 2018
1 parent cff2c2c commit 0664d3e
Show file tree
Hide file tree
Showing 9 changed files with 162 additions and 117 deletions.
Expand Up @@ -423,6 +423,7 @@ org.rapidoid.http.HttpUtils
org.rapidoid.http.HttpVerb
org.rapidoid.http.HttpWrapper
org.rapidoid.http.impl.AbstractViewResolver
org.rapidoid.http.impl.BodyRenderer
org.rapidoid.http.impl.CachedResp
org.rapidoid.http.impl.ChunkedResponse
org.rapidoid.http.impl.ErrorHandlerResolver
Expand Down
Expand Up @@ -7,9 +7,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Expand All @@ -34,6 +34,7 @@
import org.rapidoid.gui.reqinfo.ReqInfo;
import org.rapidoid.http.customize.Customization;
import org.rapidoid.http.customize.HttpResponseRenderer;
import org.rapidoid.http.handler.HandlerResultProcessor;
import org.rapidoid.http.impl.MaybeReq;
import org.rapidoid.io.Res;
import org.rapidoid.lambda.Mapper;
Expand Down Expand Up @@ -236,6 +237,12 @@ public static byte[] responseToBytes(Req req, Object result, MediaType contentTy
}
}

public static Object resultOf(Req req, Object result) {
result = HandlerResultProcessor.INSTANCE.postProcessResult(req, result);
HttpUtils.resultToResponse(req, result);
return req.response().result();
}

public static void resultToResponse(Req req, Object result) {

if (result instanceof Req) {
Expand Down
Expand Up @@ -7,9 +7,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Expand All @@ -28,6 +28,7 @@
import org.rapidoid.http.HttpWrapper;
import org.rapidoid.http.Req;
import org.rapidoid.http.RespBody;
import org.rapidoid.http.impl.BodyRenderer;
import org.rapidoid.http.impl.RespImpl;
import org.rapidoid.jpa.JPA;
import org.rapidoid.u.U;
Expand Down Expand Up @@ -58,24 +59,29 @@ public Object wrap(final Req req, final HandlerInvocation invocation) {
JPA.transaction(new Runnable() {
@Override
public void run() {
Object res;

try {
Object res = invocation.invoke();
res = invocation.invoke();

if (res instanceof Throwable) {
// throw to rollback
Throwable err = (Throwable) res;
throw U.rte("Error occurred inside the transactional web handler!", err);
}
} catch (Exception e) {
// throw to rollback
throw U.rte("Error occurred inside the transactional web handler!", e);
}

if (res instanceof Throwable) {
// throw to rollback
Throwable err = (Throwable) res;
throw U.rte("Error occurred inside the transactional web handler!", err);

} else {

// serialize the result into a HTTP response body, while still inside tx (see #153)
RespImpl resp = (RespImpl) req.response(); // TODO find a cleaner access
RespBody body = resp.resultToRespBody(res);
RespBody body = BodyRenderer.resultToRespBody(resp, res);
result.set(body);

} catch (Exception e) {
// throw to rollback
throw U.rte("Error occurred inside the transactional web handler!", e);
}

}
}, readOnly);

Expand Down
Expand Up @@ -29,23 +29,24 @@
import org.rapidoid.http.impl.RouteOptions;
import org.rapidoid.u.U;

import java.util.Collections;
import java.util.List;

@Authors("Nikolche Mihajlovski")
@Since("5.5.1")
public class HttpWrappers extends RapidoidThing {

static HttpWrapper[] assembleWrappers(FastHttp http, RouteOptions options) {
List<HttpWrapper> wrappers = U.list(getConfiguredWrappers(http, options));
List<HttpWrapper> wrappers = U.list();

wrappers.add(new HttpAuthWrapper(options.roles()));

TransactionMode txMode = U.or(options.transaction(), TransactionMode.NONE);
if (txMode != TransactionMode.NONE) {
HttpWrapper txWrapper = new HttpTxWrapper(txMode);
wrappers.add(0, txWrapper);
wrappers.add(new HttpTxWrapper(txMode));
}

HttpWrapper authWrapper = new HttpAuthWrapper(options.roles());
wrappers.add(0, authWrapper);
Collections.addAll(wrappers, getConfiguredWrappers(http, options));

return U.arrayOf(HttpWrapper.class, wrappers);
}
Expand Down
@@ -0,0 +1,104 @@
/*-
* #%L
* rapidoid-http-fast
* %%
* Copyright (C) 2014 - 2017 Nikolche Mihajlovski and contributors
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/

package org.rapidoid.http.impl;

import org.rapidoid.RapidoidThing;
import org.rapidoid.annotation.Authors;
import org.rapidoid.annotation.Since;
import org.rapidoid.http.HttpUtils;
import org.rapidoid.http.MediaType;
import org.rapidoid.http.Req;
import org.rapidoid.http.RespBody;
import org.rapidoid.http.customize.Customization;
import org.rapidoid.http.customize.HttpResponseRenderer;
import org.rapidoid.http.impl.lowlevel.HttpIO;
import org.rapidoid.log.Log;
import org.rapidoid.log.LogLevel;
import org.rapidoid.u.U;
import org.rapidoid.util.Msc;

@Authors("Nikolche Mihajlovski")
@Since("5.5.2")
public class BodyRenderer extends RapidoidThing {

static RespBody toRespBody(Req req, RespImpl resp) {
try {
return createRespBodyFromResult(req, resp);

} catch (Throwable e) {
HttpIO.INSTANCE.error(req, e, LogLevel.ERROR);

try {
return createRespBodyFromResult(req, resp);

} catch (Exception e1) {
Log.error("Internal rendering error!", e1);
return new RespBodyBytes(HttpUtils.getErrorMessageAndSetCode(resp, e1).getBytes());
}
}
}

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!");
}
}

public static RespBody resultToRespBody(RespImpl resp, Object result) {
return new RespBodyBytes(HttpUtils.responseToBytes(resp.request(), result, resp.contentType(), mediaResponseRenderer(resp)));
}

private static HttpResponseRenderer mediaResponseRenderer(RespImpl resp) {
Customization customization = Customization.of(resp.request());

if (resp.contentType().equals(MediaType.JSON)) {
return customization.jsonResponseRenderer();

} else if (resp.contentType().equals(MediaType.XML_UTF_8)) {
return customization.xmlResponseRenderer();

} else {
// defaults to json
return customization.jsonResponseRenderer();
}
}

}
Expand Up @@ -37,7 +37,6 @@
import org.rapidoid.http.impl.lowlevel.HttpIO;
import org.rapidoid.io.Upload;
import org.rapidoid.log.Log;
import org.rapidoid.log.LogLevel;
import org.rapidoid.net.abstracts.Channel;
import org.rapidoid.net.abstracts.IRequest;
import org.rapidoid.u.U;
Expand Down Expand Up @@ -566,31 +565,14 @@ private void renderResponse() {
HttpIO.INSTANCE.done(this);

} else {
// first create a response body from the result (with error handling)
RespBody body = toRespBody();
// render the response body
RespBody body = BodyRenderer.toRespBody(this, response);

// then render the response
// render the response
doRendering(response.code(), body);
}
}

private RespBody toRespBody() {
try {
return response.createRespBodyFromResult();

} catch (Throwable e) {
HttpIO.INSTANCE.error(this, e, LogLevel.ERROR);

try {
return response.createRespBodyFromResult();

} catch (Exception e1) {
Log.error("Internal rendering error!", e1);
return new RespBodyBytes(HttpUtils.getErrorMessageAndSetCode(response, e1).getBytes());
}
}
}

private String validateResponse() {
if (response == null) {
return "Response wasn't provided!";
Expand Down
Expand Up @@ -7,9 +7,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Expand All @@ -30,15 +30,16 @@
import org.rapidoid.config.Conf;
import org.rapidoid.ctx.Ctxs;
import org.rapidoid.ctx.UserInfo;
import org.rapidoid.http.*;
import org.rapidoid.http.HttpUtils;
import org.rapidoid.http.MediaType;
import org.rapidoid.http.Req;
import org.rapidoid.http.Resp;
import org.rapidoid.http.customize.Customization;
import org.rapidoid.http.customize.HttpResponseRenderer;
import org.rapidoid.http.customize.LoginProvider;
import org.rapidoid.http.customize.RolesProvider;
import org.rapidoid.io.IO;
import org.rapidoid.net.AsyncLogic;
import org.rapidoid.u.U;
import org.rapidoid.util.Msc;
import org.rapidoid.util.MscOpts;
import org.rapidoid.util.Tokens;
import org.rapidoid.web.Screen;
Expand Down Expand Up @@ -507,36 +508,6 @@ public String toString() {
'}';
}

RespBody createRespBodyFromResult() {
Object result = result();
Object body = body();

if (result instanceof RespBody) {
return (RespBody) result;

} else if (body instanceof RespBody) {
return (RespBody) body;

} else if (mvc()) {
byte[] bytes = ResponseRenderer.renderMvc(req, this);
HttpUtils.postProcessResponse(this); // 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(result);

} else {
throw U.rte("There's nothing to render!");
}
}

public RespBody resultToRespBody(Object result) {
return new RespBodyBytes(HttpUtils.responseToBytes(req, result, contentType(), mediaResponseRenderer()));
}

@Override
public Resp chunk(byte[] data) {
OutputStream chnk = out();
Expand Down Expand Up @@ -591,17 +562,4 @@ void finish() {
}
}

private HttpResponseRenderer mediaResponseRenderer() {
if (contentType.equals(MediaType.JSON)) {
return Customization.of(req).jsonResponseRenderer();

} else if (contentType.equals(MediaType.XML_UTF_8)) {
return Customization.of(req).xmlResponseRenderer();

} else {
// defaults to json
return Customization.of(req).jsonResponseRenderer();
}
}

}
Expand Up @@ -7,9 +7,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Expand All @@ -35,7 +35,6 @@
import org.rapidoid.data.JSON;
import org.rapidoid.http.*;
import org.rapidoid.http.customize.Customization;
import org.rapidoid.http.handler.HandlerResultProcessor;
import org.rapidoid.http.impl.MaybeReq;
import org.rapidoid.http.impl.ReqImpl;
import org.rapidoid.job.Jobs;
Expand Down Expand Up @@ -191,9 +190,7 @@ void error(final Req req, final Throwable error, LogLevel logLevel) {
Resp resp = req.response().code(500).result(null);
Object result = Customization.of(req).errorHandler().handleError(req, resp, error);

result = HandlerResultProcessor.INSTANCE.postProcessResult(req, result);

HttpUtils.resultToResponse(req, result);
HttpUtils.resultOf(req, result);

} catch (Exception e) {
Log.error("An error occurred inside the error handler!", e);
Expand Down

0 comments on commit 0664d3e

Please sign in to comment.