How the WebServer Serves the Preferences UI at localhost:62718 in HallelujahIM

The WebServer class wraps GCDWebServer to bind a local HTTP server to port 62718, serves static Vue.js files from the app bundle's web directory, and exposes a JSON API at /preference for reading and writing NSUserDefaults.

The dongyuwei/hallelujahim repository implements a lightweight preferences interface using an embedded web server. By navigating to http://localhost:62718/, users interact with a Vue.js application that communicates with the backend via a RESTful API. This architecture allows the input method editor to expose configuration options through a browser-based UI without external dependencies.

Starting the Local HTTP Server on Port 62718

The server initialization happens in src/WebServer.m using the GCDWebServer framework. The implementation hardcodes port 62718 and restricts binding to localhost only, preventing external network access.

static int port = 62718;                               // src/WebServer.m L20
options[GCDWebServerOption_Port] = @(port);            // src/WebServer.m L71
options[GCDWebServerOption_BindToLocalhost] = @YES;   // src/WebServer.m L72
[webServer startWithOptions:options error:nil];

This configuration ensures the preferences UI is accessible only from the local machine at http://localhost:62718/.

Serving the Static Preferences UI

Once the server starts, it registers a handler to serve static files from the web directory inside the app bundle. This directory contains index.html, index.js, vue.js, and index.css.

[webServer addGETHandlerForBasePath:@"/"
                      directoryPath:[NSString stringWithFormat:@"%@/%@", [NSBundle mainBundle].resourcePath, @"web"]
                      indexFilename:nil
                           cacheAge:3600
                 allowRangeRequests:YES];            // src/WebServer.m L36-L42

A request to http://localhost:62718/ returns index.html, which bootstraps the Vue.js single-page application.

Exposing the /preference API Endpoint

The server exposes a JSON API at /preference for reading and updating user settings stored in NSUserDefaults. The implementation handles both GET and POST methods in src/WebServer.m.

Reading Preferences (GET)

The GET handler returns the current boolean values for TRANSLATION_KEY and COMMIT_WORD_WITH_SPACE_KEY:

[webServer addHandlerForMethod:@"GET"
                          path:@"/preference"
                  requestClass:[GCDWebServerRequest class]
                  processBlock:^GCDWebServerResponse *(GCDWebServerRequest *request) {
    return [GCDWebServerDataResponse responseWithJSONObject:@{
        TRANSLATION_KEY : @([preference boolForKey:TRANSLATION_KEY]),
        COMMIT_WORD_WITH_SPACE_KEY : @([preference boolForKey:COMMIT_WORD_WITH_SPACE_KEY])
    }];
}];                                                   // src/WebServer.m L43-L53

Updating Preferences (POST)

The POST handler receives a JSON body, writes the new values to NSUserDefaults, and echoes the payload:

[webServer addHandlerForMethod:@"POST"
                          path:@"/preference"
                  requestClass:[GCDWebServerURLEncodedFormRequest class]
                  processBlock:^GCDWebServerResponse *(GCDWebServerRequest *request) {
    NSDictionary *data = ((GCDWebServerDataRequest *)request).jsonObject;
    bool showTranslation = [data[TRANSLATION_KEY] boolValue];
    [preference setBool:showTranslation forKey:TRANSLATION_KEY];
    bool commitWordWithSpace = [data[COMMIT_WORD_WITH_SPACE_KEY] boolValue];
    [preference setBool:commitWordWithSpace forKey:COMMIT_WORD_WITH_SPACE_KEY];
    return [GCDWebServerDataResponse responseWithJSONObject:data];
}];                                                   // src/WebServer.m L55-L68

Frontend Integration with Vue.js

The Vue.js frontend in web/index.html and web/index.js communicates with the /preference endpoint. On page load, it fetches current settings:

fetch("http://localhost:62718/preference")          // get current settings
  .then(r => r.json())
  .then(pref => { this.preference = pref; });

When the user submits the form, the app POSTs the updated values back to the server:

fetch("http://localhost:62718/preference", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify(this.preference)
})
.then(r => r.json())
.then(updated => { console.log("Saved:", updated); });

This creates a seamless loop where the browser-based UI reads from and writes to the application's NSUserDefaults via the local HTTP server.

Summary

  • GCDWebServer powers the WebServer singleton, binding to localhost:62718 exclusively to prevent external access.
  • Static file serving from the web/ directory delivers the Vue.js application at the root path /.
  • RESTful API at /preference handles GET requests to read NSUserDefaults and POST requests to update boolean settings for translation and commit-word-with-space features.
  • Vue.js frontend in web/index.js consumes the API, providing a reactive interface for configuring the input method editor.

Frequently Asked Questions

Why does the WebServer bind to localhost only?

The server sets GCDWebServerOption_BindToLocalhost to YES in src/WebServer.m line 72. This security measure ensures the preferences UI is accessible only from the local machine, preventing remote devices from accessing or modifying application settings through the HTTP interface.

What happens if port 62718 is already in use?

The analysis does not show explicit error handling for port conflicts in the provided code. Since the port is hardcoded to 62718 in src/WebServer.m line 20, the server would fail to start if another process occupies that port, likely returning an error through the startWithOptions:error: method's error pointer.

How does the frontend know when preferences are saved?

The POST handler in src/WebServer.m lines 55-68 returns the updated JSON payload immediately after writing to NSUserDefaults. The Vue.js frontend in web/index.js receives this response and logs the confirmation, providing immediate feedback that the settings have been persisted to the application's user defaults.

Can I access the preferences UI from another device on the network?

No. The server explicitly binds to localhost only via GCDWebServerOption_BindToLocalhost set to YES in src/WebServer.m line 72. This restriction prevents network access, ensuring only the local user can view and modify preferences through the browser interface at http://localhost:62718/.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →