Camel - HTTP request content based redirecting - apache-camel

I 'm trying to use camel for redirecting an http request based on the contents of the request body.
I 've created an endpoint for receiving http requests and I 'm able to successfully redirect my request to a different URL, using the following route;
<route>
<from uri="servlet:myapptest2?matchOnUriPrefix=true"/>
<to uri="http://sampleurl/test?bridgeEndpoint=true&throwExceptionOnFailure=false" />
</route>
But I 'm not able to figure out a way to check the http request body. My HTTP request will be having a JSON body similar to this;
{
"testLoginRequest": {
"sampleData1": [{
"key1": "val1",
"key2": "val2"
}],
"sampleData2": [{
"key1": "val1",
"key2": "val2"
}]
}
}
I want to redirect the request to a specific URL if the JSON contains the value "testLoginRequest".
I read that this should be possible like ;
from("direct:test").
choice().
when(body().contains("javainuse1"))
.to("jms:queue:javainuse1").
otherwise().
to("jms:queue:otherwise");
Since I have to use the XML DSL, I tried implementing the following route, but it doesn't seem to work;
<route>
<from uri="servlet:myapptest3?matchOnUriPrefix=true" />
<choice>
<when>
<simple>${body} contains 'testLoginRequest' </simple>
<to uri="http://sampleurlforlogin/test?bridgeEndpoint=true&throwExceptionOnFailure=false" />
</when>
</choice>
</route>
Am I following the right approach. What am I doing wrong here?

Related

React router nested routes v5 with HTTP request

I'm using react-router as following in the App.js file:
<Route exact path="/category/:categoryId">
<ProductLists />
</Route>
and is been called like this:
<RouterLink to={`/category/${category.id}`}>
{category.name}
</RouterLink>
But the problem is that when I'm trying to make the HTTP request inside the ProductLists component, it tries to put the "category" in the beginning for the request.
This is the code that makes the request:
Axios.get(
`/api/resources/products/category-id/?categoryId=${categoryId}`,
{
headers: {
'Content-Type': CONTENT_TYPE_JSON_VALUE,
},
}
So instead of doing this:
http://localhost:3000/api/resources/products/category-id/?categoryId=10a49ef4
it is doing this:
http://localhost:3000/category/api/resources/products/category-id/?categoryId=10a49ef4
Any idea why the "category" is inserted at the beginning of the request?
Thanks!
Thanks to #Yousaf I found the answer.
I just had to add baseURL: '/' like this
Axios.get(
`/api/resources/products/category-id/?categoryId=${categoryId}`,
{
baseURL: '/',
headers: {
'Content-Type': CONTENT_TYPE_JSON_VALUE,
},
}
Hope this will help someone in the future

In AngularJS how to return 404 status code for any invalid URL?

Site is developed in AngualrJS and deployed on IIS web server. Where as we have only on page i.e. Index.html since it is single page application. For SEO purpose we are using prerender.io.
Added following code in web.config file to rewrite every single URL to root path
<rule name="AngularJS" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="/" />
</rule>
Also handled all invalid URL into main.module.js with following code which will redirecting to error page.
$urlRouterProvider.otherwise(function ($injector, $location) {
var $state = $injector.get('$state');
var $rootScope = $injector.get('$rootScope');
var now = new Date(); now.setTime(now.getTime() + 1 * 1800 * 1000);
setContentCookie('dlerrorURL', $location.$$absUrl, now.toUTCString(), 'xyz.com')
$rootScope.error = true;
$state.go('app.newerror')
});
With the help of above code, status code 404 getting appeared on prerender.io, but if we look into netowrk tab in developer console it displays 200 status code for all invalid URL. Technically it is correct since we have added rule in web.config file to rewrite all the URL to root path.
After lots of finding we came to the solution that we have to keep all the URLs at server side by implementing Asp.Net MVC code and adding all routes into route.config file. So that if the URL is not matched it will return 404 status code.
But since we are having 300+ pages we are avoiding to implement the above solution. Is there any alternat way to get or set 404 status code for invalid URL.
As per my experience so far, I faced the same issue and we made few changes like this and it worked like charm for us!
Follow this steps:
Step 1:
Go to your RouteConfig.cs in your MVC application
you will see some route map like this..
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Now comment that default route and add an additional map route like this
routes.MapRoute(
name: "Home",
url: "dv/{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "CatchAll",
url: "{*any}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
in above Map route name as HOME you will see something like dv you can replace it with any keyword for you like api or any initial of your project like abc or xyz we are doing this just to seperate the server route with angular route.
REMOVE THE CODE YOU HAVE WRITTEN IN YOUR WEB CONFIG FOR URL REWRITING.
FOR PRERENDER:
Add something like this in your web.config
<configSections>
<section name="prerender" type="Prerender.io.PrerenderConfigSection, Prerender.io, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</configSections>
<prerender token="YOUR_TOKEN_HERE"></prerender>
and add prerender.io DLL to your MVC project.
Now, in system.web add something like this for prerender.
<system.web>
<httpModules>
<add name="Prerender" type="Prerender.io.PrerenderModule, Prerender.io, Version=1.0.0.2, Culture=neutral, PublicKeyToken=null"/>
</httpModules>
</system.web>
Now in the App_Start folder of your MVC application add this class name PreApplicationStartCode.cs.
public static class PreApplicationStartCode
{
private static bool _isStarting;
public static void PreStart()
{
if (!_isStarting)
{
_isStarting = true;
DynamicModuleUtility.RegisterModule(typeof(Prerender.io.PrerenderModule));
}
}
}
And in your AssemblyInfo.cs under Properties of your MVC app add something like this for prerender at the last line of the file.
[assembly: PreApplicationStartMethod(typeof(yourappnamespace.PreApplicationStartCode), "PreStart")]

React-router server side match translated routes?

I'm using react-router for server side rendering and I have locale information stored in a locales.json file. The locale information is only set after a response from an api call, which includes the current language, i.e. 'GB', 'NO', 'FR', etc., which then completes the server response and everything is fired through to the client in the correct language.
However, I'm using the react-router match method:
match({ routes, location: req.url }, (error, redirectLocation, renderProps) => { ... }
...and I need the routes to be based off the language from the api response, i.e.
// Route
<Route path={`:storeId/${locales[language].path}`} />
// locale.json
{
"GB": {
"path": "contact"
},
"NO": {
"path": "kontakt"
}
}
Is this approach possible? It's like I need to define routes after the api call is made, but to make the api call, I need routes defined.
Yes, I haven't tried your example specifically, but it is definitly possible to define routes from an api response and pass it to the "match" function.
You could try something as following:
function handleServerRendering(req, res) {
axios.get('http://localhost:3001/myCutomeRoutes')
.then(function(response){
const myRoutes = {
routes: response.data,
location: req.url
}
match(myRoutes, function(error, redirectLocation, routeContext) {
// WRITE YOUR CODE IN HERE...
})
})
.catch(function(err){
console.log('error', err);
})
}
As you can see, you firstly do an API call and then you pass the response.data to routes inside "myRoutes" constant

React-router "Cannot GET /*" except for root url

I am willing to use React-router for my application, and I am trying the example given in the doc first, which I copied below. Now when I go to localhost:3000/, I see "App" as expected, but every other page, such as localhost:3000/inbox returns "Cannot GET /inbox". What am I missing here ?
var About = React.createClass({
render: function () {
return <h2>About</h2>;
}});
var Inbox = React.createClass({
render: function () {
return <h2>Inbox</h2>;
}});
var App = React.createClass({
render () {
return (
<div><h1>App</h1>
<RouteHandler/>
</div>
)}});
var routes = (
<Route path='/' handler={App}>
<Route path="about" handler={About}/>
<Route path="inbox" handler={Inbox}/>
</Route>
);
If you are using webpack-dev-server there is an option called history-api-fallback. If set to true 404s will fallback to /index.html.
Add the option to devServer section of the Webpack config like this:
devServer: {
contentBase: 'app/ui/www',
devtool: 'eval',
hot: true,
inline: true,
port: 3000,
outputPath: buildPath,
historyApiFallback: true,
},
Link to Webpack docs: https://webpack.js.org/configuration/dev-server/
webpack-dev-server docs on Github: https://github.com/webpack/webpack-dev-server
I believe the issue is that you are making a http resource request:
GET /inbox HTTP/1.1
Host: localhost:3000
but are using client-side only routing. Are you intending on doing server side rendering too? You might need to change your router location to be HistoryLocation instead of HashLocation (the default).
The location prop of Router.run tells it where to match the routes against. If you're not running server side React, I believe you have to use Router.HashLocation (or just leave it blank).
If not, you are accessing your component the wrong way. Try using http://localhost:3000/#/inbox. It can take a little to familiarize yourself with React-Router but it is definitely worth it!
React Router Documentation - HashLocation
Simplest option: use hash history instead. The urls stay are not very nice and if you need better SEO, I'd opt for server-side rendering as well.
If you're interested in detail about this, this answer was really helpful for me: React-router urls don't work when refreshing or writting manually
The request will be sent to the server, and the directory/file does not really exists so it will return 404, so you have to tell the server to return the index page for all requests, and react will handle the rooting :
if like me, you are hosting your react app on IIS, just add a web.config file containing :
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="404" subStatusCode="-1" />
<error statusCode="404" path="/" responseMode="ExecuteURL" />
</httpErrors>
</system.webServer>
</configuration>
This will tell IIS server to return the main page to the client instead of 404 error.
I came across the same problem, if you have a server that responds to requests and a HashRouter if you are using a static file server. Instead of using BrowserRouter use HashRouter its not the perfect fix, but should solve the cannot GET "/path" error. be sure to import HashRouter from 'react-router-dom'
render() {
return (
<div>
<HashRouter>
<Blog />
</HashRouter>
</div>
);
}
source: https://github.com/ReactTraining/react-router/blob/master/packages/react-router-dom/docs/guides/basic-components.md
To add to those not helped by the answer: historyApiFallback: true works only for the first level of the url. So site.com/about will be redirected to index but site.com/about/me won't be. In this case, you need to add the rewrite option:
historyApiFallback: {
rewrites: [
{ from: /./, to: '/index.html' }
]
}
This will match using a Regex expression all routes. Take care to also add this:
output: {
// ...
publicPath: '/'
//...
},
Otherwise, the redirect will work to index.html, but index.html may have just bundle.js as the webpacked script, and will not read correctly. It should instead be '/bundle.js', which this config option will do.
I had the same problem. Finely worked with webpack-dev-server, but not with express.
The problem was in version of Express.js. I haven't noticed that it was beta (5.0.0-beta.1)
The solution is upgrading / downgrading to stable version (4.18.2 works fine).
Hope it helps!

Loading the specific page on Browser Refresh. SPA AngularJS

I am creating a new Web API and Angular application. I want to know how we can handle routes on server side. Everything is working fine. I am using ui-router for routing, when i refresh browser that its giving me.
HTTP Error 404.0 - Not Found
I want to know how we can handle this.
Code for ui-router
$stateProvider.state('login', {
url: '/',
templateUrl: templatesDirectores.wmAccount + 'login.html',
controller: 'login-controller',
controllerAs: 'vm'
})
.state('register', {
url: '/register',
templateUrl: templatesDirectores.wmAccount + 'register.html',
controller: 'register-controller',
controllerAs: 'vm'
})
.state('forgetPassword', {
url: '/forgetpassword',
templateUrl: templatesDirectores.wmAccount + 'forget-password.html',
controller: 'forget-password-controller',
controllerAs: 'vm'
})
The view is loading fine as per the configuration, but when the URL is localhost:1235/register, it's loading fine first time but when I hit the refresh button I get 404 error.
This is occurring because you are using HTML5Mode = true in your Angular Application. Angular uses "hash" (/#register) routes to handle it's routing by default, in order to ensure that the browser does not perform a page reload from the server.
Using HTML5Mode, you can suppress the #, but at a cost. The browser must be HTML5 compliant, because HTML5Mode uses HTML Push State (HistoryAPI).
Also, your server must be configured to handle requests for routes which may exist in Angular but do not exist on the server. When you directly load a page, either by typing it in or by using refresh, a request is sent to the server, with a URL that the server may not know how to handle. Your server should be configured to return your Index.html page for any routes it does not expressly handle. This configuration varies per server.
Given you stated you are using IIS to host your site, something like the following would be necessary:
Web.config:
<system.webServer>
<rewrite>
<rules>
<rule name="Main Rule" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="/" />
</rule>
</rules>
</rewrite>
</system.webServer>
Essentially, for all routes (.*), if the request is not a file or a directory, rewrite the url to return the base URL /.
This can also be done in code, something similar to this:
Global.asax:
private const string ROOT_DOCUMENT = "/default.aspx";
protected void Application_BeginRequest( Object sender, EventArgs e )
{
string url = Request.Url.LocalPath;
if ( !System.IO.File.Exists( Context.Server.MapPath( url ) ) )
Context.RewritePath( ROOT_DOCUMENT );
}
There are a few other caveats here:
Each platform handles rewrites differently. In the case of IIS, the URL is rewritten, and the remainder of the route is lost. i.e. for localhost:1235/register, you will actually load localhost:1235/, and Angular will never receive the /register route. Essentially, all routes not known by IIS will return your app entry point.
You can set up multiple entry points to your app, but any in-memory references to variables, settings, etc. will be lost when moving from one entry point to another.
Given these two points, you should always consider any external URLs to be a fresh copy of your Angular application, and handle them accordingly.
Here's another way to reroute 404's to your SPA:
<system.webServer>
<httpErrors errorMode="Custom">
<remove statusCode="404" subStatusCode="-1"/>
<error statusCode="404" prefixLanguageFilePath="" path="/spa-location.html" responseMode="ExecuteURL"/>
</httpErrors>
</system.webServer>

Resources