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.HttpVerb
org.rapidoid.http.HttpWrapper org.rapidoid.http.HttpWrapper
org.rapidoid.http.impl.AbstractViewResolver org.rapidoid.http.impl.AbstractViewResolver
org.rapidoid.http.impl.BodyRenderer
org.rapidoid.http.impl.CachedResp org.rapidoid.http.impl.CachedResp
org.rapidoid.http.impl.ChunkedResponse org.rapidoid.http.impl.ChunkedResponse
org.rapidoid.http.impl.ErrorHandlerResolver org.rapidoid.http.impl.ErrorHandlerResolver
Expand Down
Expand Up @@ -7,9 +7,9 @@
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * 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.gui.reqinfo.ReqInfo;
import org.rapidoid.http.customize.Customization; import org.rapidoid.http.customize.Customization;
import org.rapidoid.http.customize.HttpResponseRenderer; import org.rapidoid.http.customize.HttpResponseRenderer;
import org.rapidoid.http.handler.HandlerResultProcessor;
import org.rapidoid.http.impl.MaybeReq; import org.rapidoid.http.impl.MaybeReq;
import org.rapidoid.io.Res; import org.rapidoid.io.Res;
import org.rapidoid.lambda.Mapper; 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) { public static void resultToResponse(Req req, Object result) {


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

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


if (res instanceof Throwable) { } catch (Exception e) {
// throw to rollback // throw to rollback
Throwable err = (Throwable) res; throw U.rte("Error occurred inside the transactional web handler!", e);
throw U.rte("Error occurred inside the transactional web handler!", err); }
}
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) // serialize the result into a HTTP response body, while still inside tx (see #153)
RespImpl resp = (RespImpl) req.response(); // TODO find a cleaner access RespImpl resp = (RespImpl) req.response(); // TODO find a cleaner access
RespBody body = resp.resultToRespBody(res); RespBody body = BodyRenderer.resultToRespBody(resp, res);
result.set(body); result.set(body);

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

} }
}, readOnly); }, readOnly);


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


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


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


static HttpWrapper[] assembleWrappers(FastHttp http, RouteOptions options) { 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); TransactionMode txMode = U.or(options.transaction(), TransactionMode.NONE);
if (txMode != TransactionMode.NONE) { if (txMode != TransactionMode.NONE) {
HttpWrapper txWrapper = new HttpTxWrapper(txMode); wrappers.add(new HttpTxWrapper(txMode));
wrappers.add(0, txWrapper);
} }


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


return U.arrayOf(HttpWrapper.class, wrappers); 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.http.impl.lowlevel.HttpIO;
import org.rapidoid.io.Upload; import org.rapidoid.io.Upload;
import org.rapidoid.log.Log; import org.rapidoid.log.Log;
import org.rapidoid.log.LogLevel;
import org.rapidoid.net.abstracts.Channel; import org.rapidoid.net.abstracts.Channel;
import org.rapidoid.net.abstracts.IRequest; import org.rapidoid.net.abstracts.IRequest;
import org.rapidoid.u.U; import org.rapidoid.u.U;
Expand Down Expand Up @@ -566,31 +565,14 @@ private void renderResponse() {
HttpIO.INSTANCE.done(this); HttpIO.INSTANCE.done(this);


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


// then render the response // render the response
doRendering(response.code(), body); 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() { private String validateResponse() {
if (response == null) { if (response == null) {
return "Response wasn't provided!"; return "Response wasn't provided!";
Expand Down
Expand Up @@ -7,9 +7,9 @@
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * 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.config.Conf;
import org.rapidoid.ctx.Ctxs; import org.rapidoid.ctx.Ctxs;
import org.rapidoid.ctx.UserInfo; 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.Customization;
import org.rapidoid.http.customize.HttpResponseRenderer;
import org.rapidoid.http.customize.LoginProvider; import org.rapidoid.http.customize.LoginProvider;
import org.rapidoid.http.customize.RolesProvider; import org.rapidoid.http.customize.RolesProvider;
import org.rapidoid.io.IO; import org.rapidoid.io.IO;
import org.rapidoid.net.AsyncLogic; import org.rapidoid.net.AsyncLogic;
import org.rapidoid.u.U; import org.rapidoid.u.U;
import org.rapidoid.util.Msc;
import org.rapidoid.util.MscOpts; import org.rapidoid.util.MscOpts;
import org.rapidoid.util.Tokens; import org.rapidoid.util.Tokens;
import org.rapidoid.web.Screen; 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 @Override
public Resp chunk(byte[] data) { public Resp chunk(byte[] data) {
OutputStream chnk = out(); 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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * 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.data.JSON;
import org.rapidoid.http.*; import org.rapidoid.http.*;
import org.rapidoid.http.customize.Customization; import org.rapidoid.http.customize.Customization;
import org.rapidoid.http.handler.HandlerResultProcessor;
import org.rapidoid.http.impl.MaybeReq; import org.rapidoid.http.impl.MaybeReq;
import org.rapidoid.http.impl.ReqImpl; import org.rapidoid.http.impl.ReqImpl;
import org.rapidoid.job.Jobs; 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); Resp resp = req.response().code(500).result(null);
Object result = Customization.of(req).errorHandler().handleError(req, resp, error); Object result = Customization.of(req).errorHandler().handleError(req, resp, error);


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

HttpUtils.resultToResponse(req, result);


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

0 comments on commit 0664d3e

Please sign in to comment.