-
Notifications
You must be signed in to change notification settings - Fork 0
Http Server
CefContentHttpServer is the WebUserInterface plugin's small Unreal HTTP bridge for serving UTexture2D assets to a browser or another local UI client. It starts a route at GET /img, resolves an Unreal asset path, loads and caches the texture, encodes its first mip as PNG, and returns the image bytes.
Source: Source/CefContentHttpServer
Use this module when HTML or CEF content needs to display Unreal-owned images by asset path, for example:
- inventory, character, or item thumbnails;
- map and level previews;
- settings or profile images stored as Unreal textures;
- dynamic UI images that should not be copied into a separate web project;
- a simple local asset endpoint alongside the CEF browser session.
The module keeps the browser-facing request small: the client sends an Unreal asset path and receives a normal PNG response. It also caches loaded textures, caches encoded PNG bytes, and deduplicates concurrent requests for the same asset.
Use CefContentHttpServer for asset delivery and simple request/response needs. Use CefWebSocketServer for live bidirectional messages, commands, and state updates. This endpoint does not provide authentication, authorization, or a general-purpose file server; add an access-control layer before exposing it to untrusted clients.
The UCefContentHttpServerSubsystem is a UGameInstanceSubsystem. During subsystem initialization it:
- selects
UCefContentDefaultImageRequestHandlerwhen no custom handler is configured; - starts the Unreal HTTP server on port
18080; - binds the
GET /imgroute.
The default success response is:
HTTP 200
Content-Type: image/png
The route returns JSON error bodies for failed requests, with a status such as 400, 404, or 500.
Request a texture by Unreal package path:
http://localhost:18080/img?asset=/Game/Folder/T_Image
For an asset stored at:
Content/Folder/T_Image.uasset
send:
/Game/Folder/T_Image
The cache normalizes that package path to the object path /Game/Folder/T_Image.T_Image internally. Supplying the full object path is also supported.
Example browser usage:
<img src="http://localhost:18080/img?asset=/Game/UI/T_InventoryIcon" alt="Inventory icon">Example JavaScript request:
const response = await fetch(
"http://localhost:18080/img?asset=/Game/UI/T_InventoryIcon"
);
if (!response.ok) {
throw new Error(await response.text());
}
const imageBlob = await response.blob();
const imageUrl = URL.createObjectURL(imageBlob);
document.querySelector("#icon").src = imageUrl;The server reads the asset path in this order:
- query parameter
asset; - query parameter
aasset(supported as a compatibility alias); - JSON body with an
assetfield; - JSON body with an
asset=field; - raw UTF-8 body beginning with
asset=.
Examples:
GET /img?asset=/Game/UI/T_Icon
{"asset":"/Game/UI/T_Icon"}asset=/Game/UI/T_Icon
The query-string form is recommended for <img> tags and browser caching. The JSON or raw-body forms are useful when a client already builds request payloads programmatically.
Get the subsystem with Get Cef Content Http Server Subsystem from a world-context object, or use the UCefContentHttpServerBPLibrary helper.
Useful functions include:
| Function | Purpose |
|---|---|
Start Server |
Starts the listener. Pass a positive port to override the configured port; pass 0 to keep the configured port. |
Stop Server |
Stops the listener and unbinds /img. |
Is Server Running |
Checks whether the listener and route are active. |
Get Image By Package Path |
Loads an image through the module cache for game-side use. |
Get Cached Image Count |
Reports the loaded texture cache size. |
Clear Cached Images |
Clears loaded texture and encoded PNG caches. |
Set Request Handler Class |
Replaces the /img handler with a Blueprint or C++ subclass. |
The subsystem starts automatically, but calling Start Server is useful after an explicit stop or when a port override is needed.
The default port is declared on the subsystem as HttpPort = 18080. A positive argument to StartServer becomes the new listening port; 0 keeps the current configured port. Starting an already-running server is safe and leaves the current listener in place.
The subsystem stops the route during Deinitialize. It also stops before replacing a handler when SetRequestHandlerClass is called with bInRestartIfRunning = true (the default).
If the port is occupied, startup fails rather than silently selecting another port. Choose a free port and ensure the browser uses the same value.
The default handler is appropriate for PNG texture delivery. Create a subclass of UCefContentHttpImageRequestHandler when the endpoint needs custom lookup, authorization, formats, or response data.
Each handler receives FCefContentHttpImageRequestContext:
-
AssetPath- resolved asset value; -
RawBody- UTF-8 request body; -
QueryParams- parsed query values.
It fills FCefContentHttpImageResponse:
-
StatusCode; -
ContentType; -
Bodyas raw response bytes.
Minimal C++ example:
#include "Handlers/CefContentHttpImageRequestHandler.h"
UCLASS()
class UMyUiImageHandler : public UCefContentHttpImageRequestHandler
{
GENERATED_BODY()
public:
virtual bool HandleImageRequest_Implementation(
const FCefContentHttpImageRequestContext& request,
FCefContentHttpImageResponse& response,
FString& error) override
{
if (request.AssetPath.IsEmpty())
{
response.StatusCode = 400;
response.ContentType = TEXT("application/json");
error = TEXT("Missing asset path");
return false;
}
// Resolve and validate the request, then fill response.Body.
response.StatusCode = 200;
response.ContentType = TEXT("application/octet-stream");
return true;
}
};Assign the handler from game code:
if (UCefContentHttpServerSubsystem* subsystem =
GetGameInstance()->GetSubsystem<UCefContentHttpServerSubsystem>())
{
subsystem->SetRequestHandlerClass(UMyUiImageHandler::StaticClass(), true);
}The handler also supports HandleImageRequestAsync. Use it when loading, encoding, or authorization work should complete asynchronously. The built-in handler uses this path to load on the game thread, encode PNG data on a worker, cache encoded bytes, and join concurrent requests for the same asset.
There are two related caches:
-
Texture cache - loaded
UTexture2Dobjects keyed by normalized asset path. - Encoded cache - PNG byte arrays keyed by the requested asset path.
The first request may load and encode the asset. Later requests can reuse cached data. Concurrent requests for an asset already being encoded join the same in-flight operation instead of encoding it repeatedly.
Call ClearCachedImages when assets have changed or memory should be released. This clears both the loaded texture cache and encoded PNG cache. Monitor cache size with GetCachedImageCount and the module's Unreal stats when diagnosing memory use.
The default encoder reads the first texture mip and expects usable platform data with four-channel pixel data. For unusual texture formats, virtual textures, or non-UTexture2D assets, use a custom handler or encoder strategy.
| Status | Typical cause |
|---|---|
400 |
The asset value is missing. |
404 |
The asset cannot be loaded or is not found. |
500 |
The module, handler, texture data, or PNG encoder is unavailable or failed. |
Errors are returned as JSON, for example:
{"error":"Missing required 'asset' parameter"}Check that IsServerRunning is true, port 18080 is free, and the URL uses the actual configured port. Look for route-bind or listener errors in the Unreal log.
Use the Unreal object/package path, not a Windows filesystem path. Confirm the asset is a UTexture2D and that the asset is available in the running build.
Check that the texture has platform data and a valid first mip. Clear the caches after replacing or reimporting the asset, then retry.
Call SetRequestHandlerClass with the correct handler class and keep bInRestartIfRunning enabled, or stop and start the server manually after changing the handler.