Hello Claus,

While camel-graphql component doesn't document this
https://camel.apache.org/components/4.10.x/graphql-component.html,
underlying class has following:

https://github.com/apache/camel/blob/main/components/camel-graphql/src/main/java/org/apache/camel/component/graphql/GraphqlEndpoint.java

 public void setHttpClient(CloseableHttpClient httpClient) {
        this.httpClient = httpClient;
    }

can this be used to set up an http client that disables redirect as interim
and let it "error"?


Also it has a private method:
  private CloseableHttpClient createHttpClient() {
        HttpClientBuilder httpClientBuilder = HttpClients.custom();
        if (proxyHost != null) {
            String[] parts = proxyHost.split(":");
            String hostname = parts[0];
            int port = Integer.parseInt(parts[1]);
            httpClientBuilder.setProxy(new HttpHost(hostname, port));
        }

if we can add a parameter to disalble redirect handling
https://hc.apache.org/httpcomponents-client-4.5.x/current/httpclient/apidocs/org/apache/http/impl/client/HttpClientBuilder.html#disableRedirectHandling()
and invoke it in createHttpClient - it can possibly prevent a direct from
occurring.

Trying regular http route:
import org.apache.camel.builder.RouteBuilder;

public class Workaround extends RouteBuilder {

    @Override
    public void configure() throws Exception {
        from("timer:java?period=1000")
            .setBody()
                .simple("Hello Camel from ${routeId}")

                    .to("http://
https://swapi-graphql.netlify.app/.netlify/functions/index";)
                    .convertBodyTo(String.class)

            .log("${body}")
            .log("${headers}");
    }
}


Returns following:

2025-08-23 11:43:06.161  INFO 35408 --- [           main]
e.camel.impl.engine.AbstractCamelContext : Apache Camel 4.13.0 (Workaround)
started in 430ms (build:0ms init:0ms start:430ms boot:3s505ms)
2025-08-23 11:43:07.689 ERROR 35408 --- [ - timer://java]
ocessor.errorhandler.DefaultErrorHandler : Failed delivery for (MessageId:
F246E09A67CDCDC-0000000000000000 on ExchangeId:
F246E09A67CDCDC-0000000000000000). Exhausted after delivery attempt: 1
caught: org.apache.camel.http.base.HttpOperationFailedException: HTTP
operation failed invoking
https://swapi-graphql.netlify.app/.netlify/functions/index with statusCode:
301, redirectLocation: /graphql

Message History
---------------------------------------------------------------------------------------------------------------------------------------
Source                                   ID
Processor                                          Elapsed (ms)
Workaround.java:7                        route1/route1
 from[timer://java?period=1000]                              666
Workaround.java:8                        route1/setBody1
 setBody[simple{Hello Camel from ${routeId}}]                  2
Workaround.java:10                       route1/to1
http://https://swapi-graphql.netlify.app/.netlify/            0

Stacktrace
---------------------------------------------------------------------------------------------------------------------------------------
org.apache.camel.http.base.HttpOperationFailedException: HTTP operation
failed invoking https://swapi-graphql.netlify.app/.netlify/functions/index
with statusCode: 301, redirectLocation: /graphql
        at
org.apache.camel.component.http.HttpProducer.populateHttpOperationFailedException(HttpProducer.java:460)
~[camel-http-4.13.0.jar:4.13.0]
        at
org.apache.camel.component.http.HttpProducer.lambda$process$1(HttpProducer.java:283)
~[camel-http-4.13.0.jar:4.13.0]
        at
org.apache.camel.component.http.HttpProducer.executeMethod(HttpProducer.java:496)
~[camel-http-4.13.0.jar:4.13.0]
        at
org.apache.camel.component.http.HttpProducer.process(HttpProducer.java:253)
~[camel-http-4.13.0.jar:4.13.0]
        at
org.apache.camel.support.AsyncProcessorConverterHelper$ProcessorToAsyncProcessorBridge.process(AsyncProcessorConverterHelper.java:65)
[camel-support-4.13.0.jar:4.13.0]
        at
org.apache.camel.processor.SendProcessor.sendUsingProducer(SendProcessor.java:252)
[camel-core-processor-4.13.0.jar:4.13.0]
        at
org.apache.camel.processor.SendProcessor.process(SendProcessor.java:157)
[camel-core-processor-4.13.0.jar:4.13.0]
        at
org.apache.camel.processor.errorhandler.RedeliveryErrorHandler$SimpleTask.handleFirst(RedeliveryErrorHandler.java:440)
[camel-core-processor-4.13.0.jar:4.13.0]
        at
org.apache.camel.processor.errorhandler.RedeliveryErrorHandler$SimpleTask.run(RedeliveryErrorHandler.java:416)
[camel-core-processor-4.13.0.jar:4.13.0]
        at
org.apache.camel.impl.engine.DefaultReactiveExecutor$Worker.doRun(DefaultReactiveExecutor.java:199)
[camel-base-engine-4.13.0.jar:4.13.0]
        at
org.apache.camel.impl.engine.DefaultReactiveExecutor$Worker.executeReactiveWork(DefaultReactiveExecutor.java:189)
[camel-base-engine-4.13.0.jar:4.13.0]
        at
org.apache.camel.impl.engine.DefaultReactiveExecutor$Worker.tryExecuteReactiveWork(DefaultReactiveExecutor.java:166)
[camel-base-engine-4.13.0.jar:4.13.0]
        at
org.apache.camel.impl.engine.DefaultReactiveExecutor$Worker.schedule(DefaultReactiveExecutor.java:148)
[camel-base-engine-4.13.0.jar:4.13.0]
        at
org.apache.camel.impl.engine.DefaultReactiveExecutor.scheduleMain(DefaultReactiveExecutor.java:59)
[camel-base-engine-4.13.0.jar:4.13.0]
        at org.apache.camel.processor.Pipeline.process(Pipeline.java:163)
[camel-core-processor-4.13.0.jar:4.13.0]
        at
org.apache.camel.impl.engine.CamelInternalProcessor.processNonTransacted(CamelInternalProcessor.java:347)
[camel-base-engine-4.13.0.jar:4.13.0]
        at
org.apache.camel.impl.engine.CamelInternalProcessor.process(CamelInternalProcessor.java:323)
[camel-base-engine-4.13.0.jar:4.13.0]
        at
org.apache.camel.component.timer.TimerConsumer.sendTimerExchange(TimerConsumer.java:293)
[camel-timer-4.13.0.jar:4.13.0]
        at
org.apache.camel.component.timer.TimerConsumer$1.doRun(TimerConsumer.java:164)
[camel-timer-4.13.0.jar:4.13.0]
        at
org.apache.camel.component.timer.TimerConsumer$1.run(TimerConsumer.java:136)
[camel-timer-4.13.0.jar:4.13.0]
        at java.base/java.util.TimerThread.mainLoop(Timer.java:566) [?:?]
        at java.base/java.util.TimerThread.run(Timer.java:516) [?:?]

with doTry - it is able to capture following headers in Catch block (but
not location / redirect URL).

2025-08-23 11:52:17.384  INFO 15820 --- [ - timer://java]
Workaround.java:21                       : {CamelHttpResponseCode=301,
CamelHttpResponseText=Moved Permanently}


On Sat, Aug 23, 2025 at 3:14 AM Claus Ibsen <claus.ib...@gmail.com> wrote:

> Hi
>
> I created a ticket
> https://issues.apache.org/jira/browse/HTTPCLIENT-2390
>
> On Sat, Aug 23, 2025 at 8:22 AM Claus Ibsen <claus.ib...@gmail.com> wrote:
>
> > Hi
> >
> > Looking inside the HTTP client source code, then it looks like its not
> > possible.
> >
> >
> >
> org/apache/httpcomponents/client5/httpclient5/5.4.4/httpclient5-5.4.4-sources.jar!/org/apache/hc/client5/http/impl/async/AsyncRedirectExec.java:149
> >
> > There it detects that its a 301/302 and if its a POST then change that to
> > a GET
> > And there is no way to influence this, with a custom
> > RedirectStrategy implementation.
> >
> > So I think your best way is to ask the HTTP client project to see if they
> > can improve this, and maybe have a some API or new option you can set to
> > control this.
> >
> >
> >
> >
> >
> >
> >
> > On Sat, Aug 23, 2025 at 8:15 AM Claus Ibsen <claus.ib...@gmail.com>
> wrote:
> >
> >> Hi
> >>
> >> Ah okay yeah that is a special case. But it's not really a bug in Camel
> >> as you mention it should be using 308 instead.
> >> Yeah I think not many humans know about this and systems may be
> hardcoded
> >> to use 301.
> >>
> >> So if anything then its something in HTTP client that should have some
> >> option to "overrule" this 301 and treat it as a 308.
> >>
> >>
> >>
> >> On Wed, Aug 20, 2025 at 9:33 PM Chirag <chirag.sangh...@gmail.com>
> wrote:
> >>
> >>> it is v2:
> >>> rest("/v2/swapi-graphql/all-films").get()
> >>> .produces("application/json")
> >>> .to("direct:swapi-graphql-all-films2");
> >>> from("direct:swapi-graphql-all-films2")
> >>> .setBody(constant("{ allFilms { films { title director releaseDate } }
> >>> }"))
> >>> .to("graphql://
> >>> https://swapi-graphql.netlify.app/.netlify/functions/index";)
> >>> .convertBodyTo(String.class);
> >>> The reason for the failure is interesting:
> >>> 1. GraphQL component constructs POST and invokes HTTP
> >>> 2. netlify's index URL returns 301 with /graphql  - and that forces
> POST
> >>> to
> >>> be changed to GET by underlying http client.
> >>>
> >>> looking at HTTP spec - it should have been 308
> >>> https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/308
> -
> >>> but haven't seen 308 adopted widely.
> >>>
> >>> ચિરાગ/चिराग/Chirag
> >>> ------------------------------------------
> >>> Sent from My Gmail Account
> >>>
> >>>
> >>> On Wed, Aug 20, 2025 at 3:18 PM Claus Ibsen <claus.ib...@gmail.com>
> >>> wrote:
> >>>
> >>> > Hi
> >>> >
> >>> > Can you tell if its v1 or v2 in that sample code that fails (due to a
> >>> > redirect)
> >>> >
> >>> > On Tue, Aug 19, 2025 at 12:09 AM Chirag
> <w35ank...@mozmail.com.invalid
> >>> >
> >>> > wrote:
> >>> >
> >>> > > Picking up a thread from Linkedin Discussion
> >>> > >
> >>> > >
> >>> > >
> >>> >
> >>>
> https://www.linkedin.com/posts/diego-giudici-2a4a82183_apache-camel-exec-component-to-be-used-to-activity-7361417086029520896-rX9S?utm_source=share&utm_medium=member_desktop&rcm=ACoAAAADB-oBkocmID4JNAjX2CC91jH5a8sV5l4
> >>> > >
> >>> > > here is route:
> >>> > >
> >>>
> https://gist.github.com/chiragsanghavi/b83ef5babc6d02b2757ae6a9cd100281
> >>> > >
> >>> > > Technically this is not a bug, as site
> >>> > > https://swapi-graphql.netlify.app/.netlify/functions/index leads
> to
> >>> a
> >>> > > direct, which shouldn't happen in real life.
> >>> > >
> >>> > > GraphGL component initiates request using a POST, but redirect is
> >>> handled
> >>> > > by Apache Common HTTP Client - and as GET - which is where the
> >>> "query" is
> >>> > > not passed to the redirected URL.
> >>> > >
> >>> > > what will be better way to handle it ? Should such scenario be
> >>> handled by
> >>> > > passing a custom http client that disables redirect  and capture
> >>> error?
> >>> > >
> >>> > > If GraphQL component was built using camel-http underneath - it
> could
> >>> > > return many more values to make some decisions  after exchange is
> >>> called
> >>> > .
> >>> > >
> >>> >
> >>> >
> >>> > --
> >>> > Claus Ibsen
> >>> >
> >>>
> >>
> >>
> >> --
> >> Claus Ibsen
> >>
> >
> >
> > --
> > Claus Ibsen
> >
>
>
> --
> Claus Ibsen
>

Reply via email to