How to forward to an external url? - spring

My Spring based app is running under http://localhost. Another app is running under http://localhost:88. I need to achieve the following: when a user opens http://localhost/page, a content of http://localhost:88/content should be shown.
I've supposed, that I should use forwarding, like shown bellow:
#RequestMapping("/page")
public String handleUriPage() {
return "forward:http://localhost:88/content";
}
but seems like forwarding to an external URL doesn't work.
How can I achieve this behaviour with Spring?

Firstly, you specify that you want to show the content of "http://localhost:88/content" but you actually forward to "http://localhost:88" in your method.
Nevertheless, forward works with relative URLs only (served by other controllers of the same application), so you should use 'redirect:' instead.
Forward happens entirely on the server side: the Servlet container forwards the same request to the target URL, so the URL won't change in the address bar.
Redirect, on the other hand, will cause the server to respond with 302 and the Location header set to the new URL, after which the client browser will make a separate request to it, changing the URL in the address bar, of course.
UPDATE: For returning the content of the external page as it would be an internal one, I would write a separate controller method to make the request to the URL and just return its content. Something like the following:
#RequestMapping(value = "/external", produces = MediaType.TEXT_HTML_VALUE)
public void getExternalPage(#RequestParam("url") String url, HttpServletResponse response) throws IOException {
HttpClient client = HttpClients.createDefault();
HttpGet request = new HttpGet(url);
HttpResponse response1 = client.execute(request);
response.setContentType("text/html");
ByteStreams.copy(response1.getEntity().getContent(), response.getOutputStream());
}
Of course, you have many possible solutions. Here I used Apache Commons HttpClient for making the request, and Google's Guava for copying the response from that request to the resulting one.
After that, your return statement would change to the following:
return "forward:/external?url=http%3A%2F%2Flocalhost%3A88%2Fcontent"
Note how you need to encode your URL given as parameter.

Related

Create a multi-website proxy with `http-proxy`

I'm using node-http-proxy to run a proxy website. I would like to proxy any target website that the user chooses, similarly to what's done by https://www.proxysite.com/, https://www.croxyproxy.com/ or https://hide.me/en/proxy.
How would one achieve this with node-http-proxy?
Idea #1: use a ?target= query param.
My first naive idea was to add a query param to the proxy, so that the proxy can read it and redirect.
Code-wise, it would more or less look like (assuming we're deploy this to http://myproxy.com):
const BASE_URL = 'https://myproxy.com';
// handler is the unique handler of all routes.
async function handler(
req: NextApiRequest,
res: NextApiResponse
): Promise<void> {
try {
const url = new URL(req.url, BASE_URL); // For example: `https://myproxy.com?target=https://google.com`
const targetURLStr = url.searchParams.get('target'); // Get `?target=` query param.
return httpProxyMiddleware(req, res, {
changeOrigin: true,
target: targetURLStr,
});
} catch (err) {
res.status(500).json({ error: (err as Error).message });
}
}
Problem: If I deploy this code to myproxy.com, and load https://myproxy.com?target=https://google.com, then google.com is loaded, but:
if I click a link to google images, it loads https://myproxy.com/images instead of https://myproxy.com?target=https://google.com/images, also see URL as query param in proxy, how to navigate?
Idea #2: use cookies
Second idea is to read the ?target= query param like above, store its hostname in a cookie, and proxy all resources to the cookie's hostname.
So for example user wants to access https://google.com/a/b?c=d via the proxy. The flow is:
go to https://myproxy.com?target=${encodeURIComponent('https://google.com/a/b?c=d')}
proxy reads the ?target= query param, sets the hostname (https://google.com) in a cookie
proxy redirects to https://myproxy.com/a/b?c=d (307 redirect)
proxy sees a new request, and since the cookie is set, we proxy this request into node-http-proxy using cookie's target.
Code-wise, it would look like: https://gist.github.com/throwaway34241/de8a623c1925ce0acd9d75ff10746275
Problem: This works very well. But only for one proxy at a time. If I open one browser tab with https://myproxy.com?target=https://google.com, and another tab with https://myproxy.com?target=https://facebook.com, then:
first it'll set the cookie to https://google.com, and i can navigate in the 1st tab correctly
then I go to the 2nd tab (without closing the 1st one), it'll set the cookie to https://facebook.com, and I can navigate facebook on the 2nd tab correctly
but then if I go back to the first tab, it'll proxy google resources through facebook, because the cookie has been overwritten.
I'm a bit out of ideas, and am wondering how those generic proxy websites are doing. Ideally, I would not want to parse the HTML of the target website.
The idea of a Proxy is to intercept the client requests, either by ports or by backend APIs, extract the URLs of requested resources, modify them and make those requests by self from servers, and modify responses and send them back to the client.
your first approach does this except modify responses and send back modified responses.
one way to do this is to edit all links in resources return by proxy to have your web address in them, only then send them as responses back to the client.
another way is to wrap the target site in a frame, as most web proxy sites do, and have a script to crawl the page and replace all links.
there is a small problem though. javascript-based requests are mostly hardcoded in the script and it is not an easy job to replace them.
your seconds approach sounds as if it would work better, but just a sound, nothing concrete I can say. implement a tab activity checker so you can change the cookie to your active tab. please check how-to-tell-if-browser-tab-is-active discussion about that

Redirection from Spring Boot Application of External Website

I am building a Spring Boot Application with SSL enabled.
Now when I am redirecting to some external website with leading http:// explicitly.
for example http://www.example.com. But browser is redirecting it to https://www.example.com
automatically.
As I am not sure the target site is http or https. I want to redirect to the target as it is in my database.
Is there any one could help regarding this issue?
I have tried by returning redirect:http://www.example.com and ModelAndView approach. It did not work.
Note: My action can return html view or redirect to external site.
Try This :
#RequestMapping(value = "/redirect", method = RequestMethod.GET)
public void method(HttpServletResponse httpServletResponse) {
httpServletResponse.setHeader("Location", projectUrl);
httpServletResponse.setStatus(302);
}
I tried by different ways from the Application. But it never worked.
DevOps have added Load Balancer in the middle and something messed up while setting the Load Balancer rules. They have modified at their end. Now it's working fine.

Web app with multiple domains pointing to subfolders of a parent one

I’m developing an application with Spring Boot, which runs under a domain, let’s say;
parentdomain.com
From one side the users enter their content, after logging in, at parentdomain.com/admin. This content is processed and made publicly accessible at a subfolder, let’s say;
parentdomain.com/user-one-content
parentdomain.com/user-two-content and so on.
I need to point a domain for each user to his folder, for example:
userone.com should be equivalent to parentdomain.com/user-one-content
The navigation should remain in the userone.com website.
userone.com/first-page should open parentdomain.com/user-one-content/first-page.
Right now the app is installed at PWS (Pivotal Web Services), but their routing system, doesn’t provide a solution to this approach, with multiple domains pointing to subfolders of a parent one.
How could I archive this functionality?
I would leave Spring Boot alone and put in a web server in front of it. Can you install Apache or Nginx? Domain/sub-domain rerouting is out of the box in both of them.
At the end I could archive it, thanks to the advice from gspatel
With the rooting system of PWS, or other IaaS cloud provider I can root each domain to the whole application.
Implementing the preHandle method of a HandleInterceptor, I check whether the request is coming from my domain (parentdomain.com in the example). Or if it is coming from a domain of the sites, that the app is serving (userone.com in the example). In that case, I control that doesn't access the parentdomain.com, or the content of other users, forwarding the request to the user home page (user-one-content in the example).
That's an extract, of my preHadle implementation:
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
...
String URI = request.getRequestURI();
String rootURI = "/" + idweb + "/";
if(URI.equals("/") || !URI.startsWith(rootURI)){
URI = rootURI;
RequestDispatcher requestDispatcher = request.getRequestDispatcher(request.getContextPath() + URI);
requestDispatcher.forward(request, response);
}
return true;
}

What's the diference between "return new ModelAndView("redirect:surveys.html");" and "return new ModelAndView("surveys.html");"

The question is in the title. I got a Spring MVC Web App and I have to modify many things, I'm noob with this and before do anything I'm trying to understand how is made.
What's the difference between:
return new ModelAndView("redirect:surveys.hmtl");
and
return new ModelAndView("surveys.html");
Thanks.
The first one redirects:
POST or GET
browser -------------------------------------> spring controller
redirect to surveys.html (status = 302)
<------------------------------------
GET
-------------------------------------> surveys.html
final page
<-------------------------------------
The second one forwards:
POST or GET
browser -------------------------------------> spring controller
|
|
final page V
<------------------------------------- surveys.html
Redirect - sends a http 302 Redirect to the client. And then the client will send a new request to the server, with the given url.
while return new ModelAndView("surveys.html"); instruct spring to return this view to the client
From programmer perspective it is that
return new ModelAndView("redirect:surveys.hmtl");
when you use redirect you redirect your controller to another that is applicable for redirected url. Simply speaking you can have controller that handle that path. And that controller will be fired. And can do a redirection to another page. And then in HTTP response you can see redirected status 3xx not 200 as in the normal case.
return new ModelAndView("surveys.html");
When you not use redirect you only invoke View part and display your html. There is in http response 200/OK status.

T4MVC and HTTPS not showing up in URL

Im a bit confused but my URLs being rendered with T4MVC on my local IIS Express contain HTTPS in the URL. On our staging server the URL being rendered contains HTTP but are using the same code like below? Does anyone know why?
View
public static string GetSearchResultsUrl(this UrlHelper urlHelper, ActionResult actionResult)
{
return urlHelper.ActionAbsolute(actionResult.AddRouteValue(Config.ViewData.SearchResults, true));
}
public static string ActionAbsolute(this UrlHelper urlHelper, ActionResult result) {
return string.Format("{0}{1}",urlHelper.RequestContext.HttpContext.Request.Url.GetLeftPart(UriPartial.Authority),
urlHelper.RouteUrl(result.GetRouteValueDictionary()));
UPDATE
I just found out a F5 load balancer is doing the redirect from http to https using a 302 redirect.
}
There were some recent changes to automatically use https, but that should only happen if you're using the [RequireHttps] attributes. Do you know if you're using that?
See the change log for details. This was added in 2.8.0/2.8.1.
Search for 'ActionUrlHttps' in t4mvc.tt to see the relevant code.

Resources