# \[tink\_web\] Remoting: how to properly handle a binary response (i.e. a PDF document)?

**URL:** https://community.haxe.org/t/tink-web-remoting-how-to-properly-handle-a-binary-response-i-e-a-pdf-document/3448
**Category:** Haxe
**Tags:** web
**Created:** [February 5, 2022, 3:23pm UTC](https://community.haxe.org/t/tink-web-remoting-how-to-properly-handle-a-binary-response-i-e-a-pdf-document/3448 "2022-02-05T15:23:54Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![cedx](https://community.haxe.org/user_avatar/community.haxe.org/cedx/32/2377_2.png) [@cedx](https://community.haxe.org/u/cedx)
#### Post date: [February 5, 2022, 3:23pm UTC](https://community.haxe.org/t/tink-web-remoting-how-to-properly-handle-a-binary-response-i-e-a-pdf-document/3448/1 "2022-02-05T15:23:54Z")

</div>

Tinkerbell Web’s Remoting is perfect when dealing with a RESTful API that only produces JSON responses. But when an API endpoint produces some PDF document (or other binary content), it’s more complex to handle it…

My remote interface _should ideally_ look like this:

```haxe
interface RemoteApi {
  @:get('/$id')
  @:produces("application/pdf")
  function getPdfDocument(id: String): js.html.Blob;
}

```

I’m facing 2 issues…

**How to customize the “Accept” request header?**  
This header is not set, resulting in the browser’s default `Accept: */*`. How can I set the `Accept` request header?  
`@:produces("application/pdf")` seems to be ignored, and trying to add `@:header("accept", "application/pdf")` does not change anything.

**How to smoothly handle the server response?**  
Using `js.html.Blob` as response type does not work (i.e. “No reader available for mime type application/pdf”). How can I register a new response reader?

Using `tink.Chunk`, `haxe.io.Bytes` or `String` as response type results in the same thing: the server response is `tink.http.Response.IncomingResponse` instead of the expected type.

So I must write this:

```haxe
remoteApi.getPdfDocument("ABC").next(IncomingResponse.readAll).handle(outcome -> switch outcome {
	case Failure(_):
		trace("Arg!");
	case Success(chunk):
		final file = new js.html.File([chunk.toBlob()], "MyDocument.pdf", {type: "application/pdf"});
		// Do what I want with this file.
});

```

But I _ideally_ want to write that:

```haxe
remoteApi.getPdfDocument("ABC").handle(outcome -> switch outcome {
	case Failure(_):
		trace("Arg!");
	case Success(blob):
		final file = new js.html.File([blob], "MyDocument.pdf", {type: "application/pdf"});
});

```

---

<div class="post-metadata">

### Author: ![back2dos](https://community.haxe.org/user_avatar/community.haxe.org/back2dos/32/30_2.png) [@back2dos](https://community.haxe.org/u/back2dos)
#### Post date: [February 6, 2022, 9:30am UTC](https://community.haxe.org/t/tink-web-remoting-how-to-properly-handle-a-binary-response-i-e-a-pdf-document/3448/2 "2022-02-06T09:30:17Z")

</div>

If I understand what you’re after, I’d say it’s currently not possible, at least in a straightforward manner.

1. tink\_web has `@:produces` and `@:consumes` annotations for routes that produces structured data (objects, arrays, enums). The specified mime type determines how the data is represented during transfer.
2. for all other data (internally termed “opaque”), the two headers have no effect. This can be anything from plain `Bytes` / `String` / `Chunk` (with `@:header("content-type", "application/pdf")` to properly communicate content type) or even a fully formulated `OutgoingResponse`, in which case you may do what you please.
3. on opaque data, there’s currently no way to make the client generate particular `accept` headers.

This would be a solution:

```haxe
interface RemoteApi {
  @:get('/$id?header-override-content-type=application%2Fpdf')
  function getPdfDocument(id: String):haxe.io.Bytes;
}

```

To then let the “header override” take effect, you would do this with your client:

```haxe
client = client.augment({
  before: [req -> new OutgoingRequest(
    {
      var query = Query.build(),
          fields = [for (f in req.header) f],
          url = req.header.url;
      for (param in url.query)
        switch param.name.split('header-override-') {
          case ['', name]:
            fields.push(new HeaderField(name, param.value));
          default:
            query.add(param.name, param.value);
        }

      var url = url.resolve(url.path.toString()) + '?' + query.toString();
      new OutgoingRequestHeader(req.header.method, url, req.header.protocol, fields);
    },
    req.body
  )]
});

```

---

<div class="post-metadata">

### Author: ![cedx](https://community.haxe.org/user_avatar/community.haxe.org/cedx/32/2377_2.png) [@cedx](https://community.haxe.org/u/cedx)
#### Post date: [February 6, 2022, 1:26pm UTC](https://community.haxe.org/t/tink-web-remoting-how-to-properly-handle-a-binary-response-i-e-a-pdf-document/3448/3 "2022-02-06T13:26:46Z")

</div>

I was expecting something a little simpler, but as usual you still provided a solution for the first part (i.e. custom request headers). 🤗  
And for the second part (i.e. having a properly typed response) : it’s really not a big deal to use `IncomingResponse.readAll`, so I’ll stick to that.  
Thank you @back2dos for these clarifications.
