How to include Marklogic rest-api in custom rewriter code in Xquery? - url-rewriting

I'm new to url rewriting process in Marklogic and need help to resolve the below issue.
I have written Xquery implementation to redirect my API endpoints to the respective Xquery modules as /rewriter-ex/rewriter.xqy.
xquery version "1.0-ml";
let $url := xdmp:get-request-url()
return if(fn:matches($url,"/fetchRecord")) then
fn:replace($url,"/fetchRecord","/lib/fetch-record.xqy$1")
else if(fn:matches($url,"/saveRecord")) then
fn:replace($url,"/saveRecord$","/lib/save-record.xqy")
else (xdmp:set-response-code(404, "Not found"),"/no/such/resource")
And the url-rewriter path in the App server configuration is set to /rewriter-ex/rewriter.xqy and rewrite resolves globally parameter is set to true in App server.
I'm able to redirect my API urls to the respective endpoints.But I'm not able to use predefined ML Res-API endpoints like /v1/documents,it is showing 404 error as returned in the rewriter.xqy.
Is there a way I can implement rewriter to support both rest api endpoints as well as custom API endpoints?

If you'd like to create your own RESTful API on top of MarkLogic, with your own custom end-points. Please check out XQuery API for RESTful Services (XQRS).
declare
%rest:path("/fetchRecord/{$record-id}")
%rest:GET
function fetch-record($record-id as xs:string) {
fn:doc($record-id)
};
declare
%rest:path("/saveRecord/{$record-id}")
%rest:PUT("{$doc}")
%xdmp:update
function put-record($record-id as xs:string, $doc as document-node(element())) {
xdmp:document-insert($record-id, $doc)
};
Your RESTXQ Modules can sit on their own separate HTTP App Server (on their own port) and live side by side with another HTTP App Server which has the default MarkLogic REST API on it.
XQRS is totally compatible with the rest of MarkLogic's software, including Data Hub Framework, they can party together.

The REST API doesn't support customization or replacement of the default declarative rewriter configured during initialization of a REST API server. In addition, the REST API doesn't provide an XQuery API interface to the functionality of the REST API endpoints.
Instead, the recommended approach is to extend the REST API through one of the following alternatives:
Providing an endpoint module in the modules database and specifying the actual path of the module in the modules database on a request to the REST API server to invoke the endpoint without rewriting as in http://myhost:8010/the/directory/path/to/my/module.xqy
Such endpoints can be Data Service endpoints. See https://docs.marklogic.com/guide/java/DataServices
Using the /v1/invoke endpoint to invoke a main module. See https://docs.marklogic.com/guide/rest-dev/extensions#id_72813
Using a Resource Service Extension. See https://docs.marklogic.com/guide/rest-dev/extensions#id_41710
Hoping that helps,

Thanks for your answers.I'm planning to use two app servers one for rest calls and other for API calls.These two app servers will point to the same DB.Please let me know if this is a right approach.

Related

Update domain url in laravel paginate api response

I am working in Microservices architecture.
I need your guidance in my implementation that I am working correctly or not.
I and internal service [Property] which calls from API Gateway.
In Property service I am sending responses using API resources with paginate, now the issue is my property service returns its internal URL within paginate. How can I change this custom domain URL from property to API gateway?
Or if I am doing something wrong please guide me about that. How can I use/implement paginate in internal services with next page click and search features?
I want to update the domain URL in the above image.
Thanks
Laravel has withPath method for pagination since version 5.4.
You can set relative path or absolute url with this method.
I suggest you can send request with pagination base path and dynamically set inside microservice.

Is the API still the REST API if my URLs are not resourceful?

In my app, I have admin endpoints. URLs like:
http://example.com/api/admin/customers
http://example.com/api/admin/orders
http://example.com/api/admin/movies
These URIs have GET/POST/DELETE/PUT methods which mean this is the REST API.
Now, after some day, it turned out I made new API URL like the following: http://example.com/api/regular/rate_movie. I made this API because there was no gain making it resourceful. So I called it rate_movie which is a POST request.
In my app, I have many resourceful API URIs like the above and also I have so many URIs that are not resourceful and each of them is only for themselves, like /admin/get_admin, /user/store_movie.
Is my API still called RESTful API or did it die after I made different kind of API URLs?
Those additional API endpoints you describe seem to follow an RPC (remote procedure call) style. Therefore it could be misleading to refer to the overall API as RESTful.
That's not necessarily an issue if it's a small project or it's just you working on the codebase. If others are involved you might highlight the REST and RPC endpoints, perhaps noting where the differences styles are used in your code or docs.

Hyper Ledger Composer , call REST API server side or client side

I'm working on Hyper Ledger Composer and integrating the REST API in a nodejs web app "using js client side to call the API "
and I'm wondering how can I keep some interface private and prevent from show and post to it .
Should I simply call the api server side before or is there an elegant way ?
To protect access to the REST APIS, you can implement an authentication strategy - see here https://hyperledger.github.io/composer/integrating/enabling-rest-authentication.html and https://hyperledger.github.io/composer/integrating/enabling-multiuser.html (the latter requires that authentication is enabled).
A tutorial on using one such strategy - eg using Google OAUTH2 as an auth provider - is shown here -> https://hyperledger.github.io/composer/next/tutorials/google_oauth2_rest
There is another way to develop your own rest api using NodeJs sdk.
You can connect to the network using Cards and perform any action using BusinessNetworkConnection class and factory object.
Read [https://hyperledger.github.io/composer/v0.16/applications/node][1]

Mock OAuth server for testing

I'd like to know if it is possible to simulate the oAuth(1,2) authentication flow. I'd like to test without the need to connect to the provider itself. It should be possible as it is just some communication exchange. I'm not looking for something like this where they still communicate with remote server. I'd like to be completely offline, when testing.
Maybe I can run my own oAuth server. I should be using Google oAuth services so the server should behave same like they do. Does google provide some code for their oAuth server, or is it possible to create some fake server. Note the test should be more integration test. I would like to command the server to return some predefined responses. Switching to live oAuth providers will be just changing the remote URL.
Maybe just some http server is ok, I just need to care about the proper format of communicated messages.
Take a look at Client Side REST Tests section of Spring Reference docs. With this support you can easily fake the server and record desired behaviour into MockRestServiceServer.
Here are some examples I created.
Please see steps below to mock OAuth2 token to be used for faster local development using SOAPUI.
Steps:
Create a REST soapUI project, create a POST resource for URL "http://localhost:9045/oauth/token".
Create a Mock Service for above resource.
Create a Mock response as shown below, you can add your own parameters and values depending on your requirements.
{
"access_token":"MockOauth2TokenForLocaldevelopmentnTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3",
"token_type":"bearer",
"expires_in":35999,
"scope":"read write",
"jti":"4d540b94-1854-45fa-b1d6-c2039d94b681"
}
Start the mock service.
Test using your local REST POST request.
Mock Response:
Mock Oauth2 SOAPUI testing:

Spring authentication through REST Service

I have a Webapp that consists of a REST API, and then another app that represents a frontend of this API. Both of this apps are developed using Spring.
Currently my REST api is not secured and data can be accessed directly by calling the REST endpoint without additional security info.
My frontend does have a login form (I'm using Spring Security for that), but does not have access to a database (the only access is through the REST endpoint). So the login process is done through an extension of the AuthenticationProvider that calls the REST api with the user and password and then responds with the authentication result. No authentication/authorization is kept on the REST side since to my knowledge this protocol should be stateless.
The problem is I need to incorporate ACL into my app, so that a user can only see those resources he's authorized to see (i.e. those he created). But given that my authentication process takes place on the frontend layer (which is where I keep a session attribute with the user info), I have two main problems:
How can I secure my REST channel?
How can I know which user is making the request on every communication, without explicitly passing the userdetails in each API request? is this even possible?
Doing it stateless and making two separate web application usually is overkill.
What I usually end up doing is.
Make my RestAPI stateful, because usually scaling is not an issue and simple form authentication will suffice.
Combine a Rest API/HTML Client in one Webapplication. If you want to keep it modular, you could create a Rest API module and integrate it as a JAR file in the lib folder of your web app.
Here is also some thread which goes through different alternatives for a rest API.
How to do authentication with a REST API right? (Browser + Native clients)

Resources