Deal with `private-user-images` when Fetching GitHub Discussion Body

Published in Blog/en on 12/9/2023, last edited on 1/1/1970.

When I built the new version of this blog, I used the bodyHTML that was provided by the GitHub Discussions API to improve performance. Everything went well at first, but when I set a cache for the content, the images were all broken. I found private-user-images.githubusercontent.com maybe caused this problem. This blog will introduce how I dealt with it.

Broken Images

I set a cache for the API to improve the performance and avoid extra requests. At first, I set the max-age to 60 * 60 which means an hour. However, about 5 more minutes later, all the images in the article were broken. When I opened the developer panel in my browser, I found that the source URLs of these images were not the original URL.

In the editor of the discussion body, my image URL was:

![](https://github.com/ocoke/Biscus/assets/71591824/b6b47ca0-f77c-432a-8c0f-942a9b204b0a)

However, when it was rendered to HTML by the API, it turned into:

<img src="https://private-user-images.githubusercontent.com/71591824/286707243-b6b47ca0-f77c-432a-8c0f-942a9b204b0a.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTEiLCJleHAiOjE3MDIwOTQ0MjMsIm5iZiI6MTcwMjA5NDEyMywicGF0aCI6Ii83MTU5MTgyNC8yODY3MDcyNDMtYjZiNDdjYTAtZjc3Yy00MzJhLThjMGYtOTQyYTliMjA0YjBhLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFJV05KWUFYNENTVkVINTNBJTJGMjAyMzEyMDklMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjMxMjA5VDAzNTUyM1omWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWI5ZGQ3ZTNhN2VkZGI1ZTM0MDljMTM2MDAwMTMzZDY1YjdiMTdmYjBiYmZiOTQxYzEyMTlhNWQxY2U5OWJjYzcmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.xw9990CeWP9d-lOCY_Be1co9hATFX-XYjXZCx2CnQF0" alt="" style="max-width: 100%;">

The URL became super long with a token in it, and the source domain became private-user-images.githubusercontent.com. I found the token was in JWT format (and also the query key mentioned that).

Decode JWT

Okay, let's figure out this from the ?jwt=.

Open https://jwt.io/ , and paste the full token into the Encoded.

image

Then, we can find there are several useful pieces of information in the payload.

For example, the exp is for the expiration time, and the nbf is for the not valid before.

image

So we can infer that the expiration time for the image is 5 minutes. Because we set an hour cache at first, after the first 5 minutes, the images will be unavailable.

Solution

We can set the cache to 5 minutes to avoid the expiration happening. It will work and this is the easiest way to solve this issue.

We can also fetch body with the API to return the raw markdown format body. Then, we'll need to match and get all the source images' URLs to replace them (although this is not a good idea).

Or we can render the markdown content by ourselves or call /markdown API on api.github.com.