Skip to content

Commit

Permalink
Refactored handlers for non-resource request.
Browse files Browse the repository at this point in the history
Introduced a generic RequestHandler interface. Refactored existing documentation handler, multiplexed request handler and debug request handler to use this interface.

Collapse BaseRestServer with RestLiServer as its not used.

Removed deprecated InvokeAware and related code. It's not used at LinkedIn.

RB=1107522
G=si-dev
R=kbalasub,nshankar,mnchen
A=mnchen
  • Loading branch information
Xiao Ma committed Sep 27, 2017
1 parent 1787328 commit bf0d8a7
Show file tree
Hide file tree
Showing 18 changed files with 546 additions and 672 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG
Expand Up @@ -3,6 +3,11 @@
(RB=1109051)
Expose remote port number in the request context in both server and client sides

(RB=1107522)
Introduced a generic RequestHandler interface. Refactored existing documentation handler, multiplexed request handler and debug request handler to use this interface.
Collapse BaseRestServer with RestLiServer as its not used.
Removed deprecated InvokeAware and related code. It's not used at LinkedIn.

15.0.3
-------
(RB=1091414)
Expand Down
Expand Up @@ -17,13 +17,16 @@
package com.linkedin.restli.docgen;


import com.linkedin.common.callback.Callback;
import com.linkedin.data.schema.DataSchemaResolver;
import com.linkedin.data.schema.SchemaParserFactory;
import com.linkedin.data.schema.resolver.ClasspathResourceDataSchemaResolver;
import com.linkedin.jersey.api.uri.UriBuilder;
import com.linkedin.jersey.api.uri.UriComponent;
import com.linkedin.jersey.core.util.MultivaluedMap;
import com.linkedin.r2.message.Request;
import com.linkedin.r2.message.RequestContext;
import com.linkedin.r2.message.rest.RestRequest;
import com.linkedin.r2.message.rest.RestResponse;
import com.linkedin.r2.message.rest.RestResponseBuilder;
import com.linkedin.restli.common.HttpMethod;
Expand Down Expand Up @@ -62,7 +65,7 @@ public void initialize(RestLiConfig config, Map<String, ResourceModel> rootResou
}

@Override
public boolean isDocumentationRequest(Request request)
public boolean shouldHandle(Request request)
{
final String path = request.getURI().getRawPath();
final List<UriComponent.PathSegment> pathSegments = UriComponent.decodePath(path, true);
Expand All @@ -73,8 +76,21 @@ public boolean isDocumentationRequest(Request request)
}

@Override
public void handleRequest(RestRequest request, RequestContext requestContext, Callback<RestResponse> callback)
{
try
{
RestResponse response = processDocumentationRequest(request);
callback.onSuccess(response);
}
catch (Exception e)
{
callback.onError(e);
}
}

@SuppressWarnings("fallthrough")
public RestResponse processDocumentationRequest(Request request)
private RestResponse processDocumentationRequest(Request request)
{
final String path = request.getURI().getRawPath();
final List<UriComponent.PathSegment> pathSegments = UriComponent.decodePath(path, true);
Expand Down
Expand Up @@ -67,6 +67,6 @@ public Object[][] dataProvider()
@Test(dataProvider = "data")
public void testIsDocumentationRequest(RestRequest restRequest, boolean expectedIsDocumentationRequest)
{
Assert.assertEquals(DEFAULT_HANDLER.isDocumentationRequest(restRequest), expectedIsDocumentationRequest);
Assert.assertEquals(DEFAULT_HANDLER.shouldHandle(restRequest), expectedIsDocumentationRequest);
}
}
Expand Up @@ -91,9 +91,9 @@ public void handleRequest(final RestRequest request,
{
//Find out the path coming after the "__debug" path segment
String fullPath = request.getURI().getPath();
int debugSegmentIndex = fullPath.indexOf(RestLiServer.DEBUG_PATH_SEGMENT);
int debugSegmentIndex = fullPath.indexOf(DelegatingDebugRequestHandler.DEBUG_PATH_SEGMENT);
final String debugHandlerPath = fullPath.substring(
debugSegmentIndex + RestLiServer.DEBUG_PATH_SEGMENT.length() + 1);
debugSegmentIndex + DelegatingDebugRequestHandler.DEBUG_PATH_SEGMENT.length() + 1);

assert (debugHandlerPath.startsWith(HANDLER_ID));

Expand Down
Expand Up @@ -22,7 +22,6 @@
import com.linkedin.data.template.RecordTemplate;
import com.linkedin.restli.common.ResourceMethod;
import com.linkedin.restli.server.ResourceLevel;
import com.linkedin.restli.server.RestLiMethodContext;

import java.lang.reflect.Method;
import java.util.ArrayList;
Expand All @@ -32,9 +31,7 @@
/**
* @author dellamag
*/
//TODO: Remove this once use of InvokeAware has been discontinued.
@SuppressWarnings("deprecation")
public class ResourceMethodDescriptor implements RestLiMethodContext
public class ResourceMethodDescriptor
{
public static enum InterfaceType
{
Expand Down Expand Up @@ -287,7 +284,6 @@ public List<Parameter<?>> getParametersWithType(final Parameter.ParamType type)
* @return parameter value
*/
@SuppressWarnings("unchecked")

public <T> Parameter<T> getParameter(final String name)
{
for (Parameter<?> p : _parameters)
Expand All @@ -304,7 +300,6 @@ public <T> Parameter<T> getParameter(final String name)
/**
* @return method finder name
*/
@Override
public String getFinderName()
{
return _finderName;
Expand All @@ -315,25 +310,21 @@ public Class<? extends RecordTemplate> getCollectionCustomMetadataType()
return _collectionCustomMetadataType;
}

@Override
public String getActionName()
{
return _actionName;
}

@Override
public String getResourceName()
{
return _resourceModel.getName();
}

@Override
public String getNamespace()
{
return _resourceModel.getNamespace();
}

@Override
public ResourceMethod getMethodType()
{
return _type;
Expand Down

This file was deleted.

@@ -0,0 +1,129 @@
/*
Copyright (c) 2017 LinkedIn Corp.
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.
*/

package com.linkedin.restli.server;

import com.linkedin.common.callback.Callback;
import com.linkedin.jersey.api.uri.UriBuilder;
import com.linkedin.r2.message.Request;
import com.linkedin.r2.message.RequestContext;
import com.linkedin.r2.message.rest.RestRequest;
import com.linkedin.r2.message.rest.RestRequestBuilder;
import com.linkedin.r2.message.rest.RestResponse;
import com.linkedin.r2.util.URIUtil;
import com.linkedin.restli.common.attachments.RestLiAttachmentReader;


/**
* A handler for debug request. It delegates the handling to the underlying {@link RestLiDebugRequestHandler}.
*
* @author xma
*/
class DelegatingDebugRequestHandler implements RequestHandler
{
static final String DEBUG_PATH_SEGMENT = "__debug";

private final RestLiDebugRequestHandler _delegate;
private final RestLiServer _restLiServer;

DelegatingDebugRequestHandler(RestLiDebugRequestHandler delegate, RestLiServer restLiServer)
{
_delegate = delegate;
_restLiServer = restLiServer;
}

@Override
public boolean shouldHandle(Request request)
{
// Typically, a debug request should have the following pattern in its URI path
// <base URI>/__debug/<debug handler ID>/<Rest.li request path>
String[] pathSegments = URIUtil.tokenizePath(request.getURI().getPath());
String debugHandlerId = null;

for (int i = 0; i < pathSegments.length; ++i)
{
String pathSegment = pathSegments[i];
if (pathSegment.equals(DEBUG_PATH_SEGMENT))
{
if (i < pathSegments.length - 1)
{
debugHandlerId = pathSegments[i + 1];
}
break;
}
}

return _delegate.getHandlerId().equals(debugHandlerId);
}

@Override
public void handleRequest(RestRequest request, RequestContext requestContext, Callback<RestResponse> callback)
{
_delegate.handleRequest(request,
requestContext,
new ResourceDebugRequestHandlerImpl(),
null, // Attachment not supported for debugging.
new RestResponseExecutionCallbackAdapter(callback));
}

private class ResourceDebugRequestHandlerImpl implements RestLiDebugRequestHandler.ResourceDebugRequestHandler
{
@Override
public void handleRequest(final RestRequest request,
final RequestContext requestContext,
final RequestExecutionCallback<RestResponse> callback)
{
// Create a new request at this point from the debug request by removing the path suffix
// starting with "__debug".
String fullPath = request.getURI().getPath();
int debugSegmentIndex = fullPath.indexOf(DEBUG_PATH_SEGMENT);

RestRequestBuilder requestBuilder = new RestRequestBuilder(request);

UriBuilder uriBuilder = UriBuilder.fromUri(request.getURI());
uriBuilder.replacePath(request.getURI().getPath().substring(0, debugSegmentIndex - 1));
requestBuilder.setURI(uriBuilder.build());

_restLiServer.handleResourceRequest(requestBuilder.build(), requestContext, callback, null, true);
}
}

private class RestResponseExecutionCallbackAdapter implements RequestExecutionCallback<RestResponse>
{
private final Callback<RestResponse> _wrappedCallback;

RestResponseExecutionCallbackAdapter(Callback<RestResponse> wrappedCallback)
{
_wrappedCallback = wrappedCallback;
}

@Override
public void onError(final Throwable e, final RequestExecutionReport executionReport,
final RestLiAttachmentReader requestAttachmentReader,
final RestLiResponseAttachments responseAttachments)
{
_wrappedCallback.onError(e);
}

@Override
public void onSuccess(final RestResponse result, final RequestExecutionReport executionReport,
final RestLiResponseAttachments responseAttachments)
{
_wrappedCallback.onSuccess(result);
}
}

}

0 comments on commit bf0d8a7

Please sign in to comment.