# Component choosing to proxy a response

**URL:** <https://community.bloomreach.com/t/component-choosing-to-proxy-a-response/795>\
**Category:** Experience Manager (PaaS/OnPrem)\
**Created:** [February 5, 2019, 10:34pm UTC](https://community.bloomreach.com/t/component-choosing-to-proxy-a-response/795 "2019-02-05T22:34:09Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![itGumby](https://yyz1.discourse-cdn.com/flex027/user_avatar/community.bloomreach.com/itgumby/32/1326_2.png) [@itGumby](https://community.bloomreach.com/u/itGumby)\
**Post date:** [February 5, 2019, 10:34pm UTC](https://community.bloomreach.com/t/component-choosing-to-proxy-a-response/795/1 "2019-02-05T22:34:09Z")

</div>

I have a page component that most of the time adds attribute(s) to the hstRequest and passes on to the freemarker templates for rendering.

However, in some cases, I need the component to proxy an entire response and send the other response instead (for the entire page). Instead, i get the proxied response inlined in the middle of my page. How should I solve this cleanly?

```
public class MyComponent extends BaseHstComponent {
    @Override
    public void doBeforeRender(HstRequest hstRequest, HstResponse hstResponse) throws HstComponentException {
        MyData data = dao.fetch(hstRequest.getPathInfo());
        if (shouldProxy(data) ) {
            // proper steps
        }
    }
}

```

Do I need to forward the request to a different sitemapitem or even a proxyservlet (such as [https://github.com/mitre/HTTP-Proxy-Servlet](https://github.com/mitre/HTTP-Proxy-Servlet) or Netflix Zuul [https://spring.io/guides/gs/routing-and-filtering/](https://spring.io/guides/gs/routing-and-filtering/)? I don’t want to build a filter because the filter would do the same work as the component to fetch the data and determine if a proxy is required.

---

<div class="post-metadata">

**Author:** ![woonsanko](https://avatars.discourse-cdn.com/v4/letter/w/b5a626/32.png) [@woonsanko](https://community.bloomreach.com/u/woonsanko)\
**Post date:** [February 5, 2019, 11:09pm UTC](https://community.bloomreach.com/t/component-choosing-to-proxy-a-response/795/2 "2019-02-05T23:09:55Z")

</div>

> [@itGumby](#):
>
> How should I solve this cleanly?

First, configure the reverse-proxy servlet [1] independently from HST things. For example, /site/rproxy/\*\* should be handled by the reverse-proxy servlet. i.e, /site/rproxy/example/a/b/c.html → [http://www.example.com/a/b/c.html](http://www.example.com/a/b/c.html).  
Second, you should be able to build the proxy request path (e.g, “/rproxy/a/b/c.html”) in your component.  
Third, change the `renderPath` dynamically in your `#doBeforeRender()`. e.g, `hstResponse.setRenderPath("/rproxy/a/b/c.html")`.

Then it should do the trick.

Woonsan

[1] [ServletProxy - Apache Tomcat - Apache Software Foundation](https://wiki.apache.org/tomcat/ServletProxy)  
The fourth option, “Apache Portals WebContent-2 Reverse Proxy Module”, is really flexible.

---

<div class="post-metadata">

**Author:** ![itGumby](https://yyz1.discourse-cdn.com/flex027/user_avatar/community.bloomreach.com/itgumby/32/1326_2.png) [@itGumby](https://community.bloomreach.com/u/itGumby)\
**Post date:** [February 6, 2019, 10:59pm UTC](https://community.bloomreach.com/t/component-choosing-to-proxy-a-response/795/3 "2019-02-06T22:59:32Z")

</div>

I followed the instructions on [http://portals.apache.org/applications/webcontent2/reverse-proxy-module.html](http://portals.apache.org/applications/webcontent2/reverse-proxy-module.html) and I get “ResolvedSiteMapItemImpl cannot be created correctly” in STDOUT, 404/“Not Found” on the page.

site/pom.xml:

```
<dependency>
    <!-- https://portals.apache.org/applications/webcontent2/reverse-proxy-module.html -->
    <groupId>org.apache.portals.applications</groupId>
    <artifactId>apa-webcontent2-reverse-proxy</artifactId>
    <version>2.0</version>
</dependency>

```

site WEB-INF/web.xml:

```
<servlet>
    <servlet-name>ReverseProxyServlet</servlet-name>
    <servlet-class>org.apache.portals.applications.webcontent2.proxy.servlet.SimpleReverseProxyServlet</servlet-class>
    <init-param>
        <param-name>mappings</param-name>
        <param-value>/WEB-INF/rproxy-mappings.yaml</param-value>
    </init-param>
    <init-param>
        <param-name>ssl-hostname-verifier</param-name>
        <param-value>ALLOW_ALL_HOSTNAME_VERIFIER</param-value>
    </init-param>
</servlet>
<servlet-mapping>
  <servlet-name>ReverseProxyServlet</servlet-name>
  <url-pattern>/reverse-proxyservlet/*</url-pattern>
</servlet-mapping>

```

site WEB-INF/rproxy-mappings.yaml:

```
--- !simple
local: /portals/applications/
remote: http://portals.apache.org/applications/
contentRewriters:
    text/html: !!org.apache.portals.applications.webcontent2.proxy.rewriter.DefaultReverseProxyTextLineContentRewriter []

```

But I get a 404/Not Found when I browse to [http://localhost:8080/site/reverse-proxyservlet/portals/applications/webcontent2/index.html](http://localhost:8080/site/reverse-proxyservlet/portals/applications/webcontent2/index.html) (I would expect it to render the same as [http://portals.apache.org/applications/webcontent2/index.html](http://portals.apache.org/applications/webcontent2/index.html))

STDOUT shows:

```
[INFO] [talledLocalContainer] 06.02.2019 15:58:54 WARN http-nio-8080-exec-6 [ResolvedSiteMapItemImpl.resolveComponentConfiguration:191] ResolvedSiteMapItemImpl cannot be created correctly, because the component configuration id hst:pages/pagenotfound cannot be found.

```

Am I integrating these wrong?

---

<div class="post-metadata">

**Author:** ![woonsanko](https://avatars.discourse-cdn.com/v4/letter/w/b5a626/32.png) [@woonsanko](https://community.bloomreach.com/u/woonsanko)\
**Post date:** [February 7, 2019, 12:10am UTC](https://community.bloomreach.com/t/component-choosing-to-proxy-a-response/795/4 "2019-02-07T00:10:19Z")

</div>

That’s because `HstFilter` is still taking the control when you make a request at /reverse-proxyservlet/…  
As the request path should not be handled by `HstFilter` like normal HST sitemap items, and the reverse proxy servlet has nothing to do with HST-2, you should configure the path to be bypassed by `HstFilter`:

- copy `/hst:hst/hst:configurations/hst:default/hst:sitemap/binaries` to `/hst:hst/hst:configurations/hst:default/hst:sitemap/reverse-proxyservlet` (including children).
- remove `hst:refId`.

Then the reverse proxy servlet will work independently.

Woonsan

---

<div class="post-metadata">

**Author:** ![itGumby](https://yyz1.discourse-cdn.com/flex027/user_avatar/community.bloomreach.com/itgumby/32/1326_2.png) [@itGumby](https://community.bloomreach.com/u/itGumby)\
**Post date:** [February 7, 2019, 3:34pm UTC](https://community.bloomreach.com/t/component-choosing-to-proxy-a-response/795/5 "2019-02-07T15:34:22Z")

</div>

Thanks! That resolved the proxy issue; now I can proceed with forwarding to it.

---

<div class="post-metadata">

**Author:** ![itGumby](https://yyz1.discourse-cdn.com/flex027/user_avatar/community.bloomreach.com/itgumby/32/1326_2.png) [@itGumby](https://community.bloomreach.com/u/itGumby)\
**Post date:** [February 8, 2019, 3:57pm UTC](https://community.bloomreach.com/t/component-choosing-to-proxy-a-response/795/6 "2019-02-08T15:57:58Z")

</div>

I have the proxy solution working. And I have the component setting the renderPath - but that only inlines the (proxied) response in the middle of the page via `hstResponse.setRenderPath(proxyPath)`

Is there a way to not include the header/footer of the page? I want the response to ONLY have the output of the proxy, kind of like how a siteMapItemHandler can change the resolvedSiteMapItem.

Normally, we would handle this in a SiteMapItemHandler to change the resolvedSiteMapItem - but I wouldn’t know if I want to change the siteMapItem until the component has called an API (to determine if I proxy or not). If I don’t proxy, the API call returns an object that the component reacts to.

---

<div class="post-metadata">

**Author:** ![itGumby](https://yyz1.discourse-cdn.com/flex027/user_avatar/community.bloomreach.com/itgumby/32/1326_2.png) [@itGumby](https://community.bloomreach.com/u/itGumby)\
**Post date:** [February 8, 2019, 4:11pm UTC](https://community.bloomreach.com/t/component-choosing-to-proxy-a-response/795/7 "2019-02-08T16:11:53Z")

</div>

I guess my real question should be:

- can my siteMapItemHandler call the API and “pass” the resulting object to the component somehow (if so, how)
- OR can my component change the resolvedSiteMapItem kind of after the fact
- =\> I really don’t want to call the same API twice.

---

<div class="post-metadata">

**Author:** ![woonsanko](https://avatars.discourse-cdn.com/v4/letter/w/b5a626/32.png) [@woonsanko](https://community.bloomreach.com/u/woonsanko)\
**Post date:** [February 8, 2019, 11:08pm UTC](https://community.bloomreach.com/t/component-choosing-to-proxy-a-response/795/8 "2019-02-08T23:08:13Z")

</div>

> [@itGumby](#):
>
> - can my siteMapItemHandler call the API and “pass” the resulting object to the component somehow (if so, how)

By “the API”, do you mean the backend web service you wanted to do reverse-proxying in an HstComponent?  
If so, what does the response look like? JSON, XML or HTML?

---

<div class="post-metadata">

**Author:** ![itGumby](https://yyz1.discourse-cdn.com/flex027/user_avatar/community.bloomreach.com/itgumby/32/1326_2.png) [@itGumby](https://community.bloomreach.com/u/itGumby)\
**Post date:** [February 8, 2019, 11:28pm UTC](https://community.bloomreach.com/t/component-choosing-to-proxy-a-response/795/9 "2019-02-08T23:28:28Z")

</div>

The pieces are:

- JSON API returns JSON if 200 response, but 204, 404 response codes have no JSON and are significant
- HTML resources to proxy in certain cases
- SiteMapItemHandler (currently just looks at the hstRequest.getPathInfo() to determine if it meets certain cases)
- RenderComponent that calls the API and handles at least 3 cases.

Current processing ends up inlining the proxied response in middle of the page. Want the proxied HTML resource to BE the response if used.

My gut is telling me that the SiteMapItemHandler should call the JSON API. Depending on the response code, it should:

1. 200 =\> Deserialize JSON and “pass” object to the Component
2. 204 =\> proxy by resolving to new `ResolvedSiteMapItemImpl` with proxy path (that maps to external HTML)
3. 404 =\> resolve to a “not found” siteMapItem
4. ??? =\> there might also be an “expired” case

I want to avoid having both the siteMapItemHandler, Component both calling the same API with the same data.
