Skip to content

json #371

@bphd

Description

@bphd
 diff --unified <(curl -s https://raw.githubusercontent.com/ouchadam/chat-engine/main/matrix/matrix-http-ktor/src/main/kotlin/app/dapk/st/matrix/http/ktor/internal/KtorMatrixHttpClient.kt) <(wl-paste)
--- /proc/self/fd/14    2026-02-09 15:22:25.395176343 +0100
+++ /proc/self/fd/16    2026-02-09 15:22:25.395176343 +0100
@@ -16,7 +16,7 @@
 ) : MatrixHttpClient {
 
     @Suppress("UNCHECKED_CAST")
-    override suspend fun <T : Any> execute(request: MatrixHttpClient.HttpRequest<T>): T {
+    override suspend fun <T> execute(request: MatrixHttpClient.HttpRequest<T>): T {
         return when {
             !request.authenticated -> {
                 request.execute { buildRequest(credentials = null, request) }
@@ -61,12 +61,8 @@
         }
     }
 
-
     suspend fun authenticate(): UserCredentials {
         throw Error() // TODO
-//        val tokenResult = client.request<String> { buildRequest(AuthEndpoint.anonAccessToken()) }
-//        tokenProvider.update(tokenResult.accessToken)
-//        return tokenResult.accessToken
     }
 
     @OptIn(InternalAPI::class)
@@ -88,6 +84,13 @@
                 append(it.first, it.second)
             }
         }
+        
+        // FIX: Tell the server we're sending JSON data
+        // Without this, the server rejects login requests with "Invalid Content-Type header"
+        if (request.body != null && request.method != Method.GET) {
+            contentType(ContentType.Application.Json)
+        }
+        
         this.body = request.body
     }
 
## Bug Report: Can't Log In - "Invalid Content-Type header" Error

**What happens:**
When trying to log in, the app shows this error:
\```
M_NOT_JSON: Invalid Content-Type header: expected application/json
\```

**Why it happens:**
The app forgets to tell the server "I'm sending JSON data" when making login requests. It's like mailing a letter without writing the return address - the server doesn't know how to read it.

**Where the bug is:**
File: `matrix/matrix-http-ktor/src/main/kotlin/app/dapk/st/matrix/http/ktor/internal/KtorMatrixHttpClient.kt`

**The fix:**
Add this line before `this.body = request.body` (around line 88):

\```kotlin
if (request.body != null && request.method != Method.GET) {
    contentType(ContentType.Application.Json)
}
\```

**What this does:**
It tells the server "Hey, the data I'm sending is JSON format" so the server knows how to understand it.

**Title:** Fix login error - missing Content-Type header

**Body:**
\````
## Problem
Users can't log in. The server returns:
"M_NOT_JSON: Invalid Content-Type header: expected application/json"

## Root Cause
In KtorMatrixHttpClient.kt, when sending POST requests (like login), 
the app doesn't set the Content-Type header to "application/json".

## Fix
In the buildRequest() function, add:

if (request.body != null && request.method != Method.GET) {
    contentType(ContentType.Application.Json)
}

This should be added right before "this.body = request.body"

## Files to change
- matrix/matrix-http-ktor/src/main/kotlin/app/dapk/st/matrix/http/ktor/internal/KtorMatrixHttpClient.kt

## Impact
This will fix login for all users currently getting the M_NOT_JSON error.
\```

I found the exact location of the bug in `KtorMatrixHttpClient.kt`. Look at the `buildRequest` function (lines 68-85):

\```kotlin
private fun <T> HttpRequestBuilder.buildRequest(
    credentials: UserCredentials?,
    request: MatrixHttpClient.HttpRequest<T>
) {
    val host =
        request.baseUrl ?: credentials?.homeServer?.value ?: throw Error()
    this.url("$host${request.path}")
    this.method = when (request.method) {
        Method.GET -> HttpMethod.Get
        Method.POST -> HttpMethod.Post
        Method.DELETE -> HttpMethod.Delete
        Method.PUT -> HttpMethod.Put
    }
    this.headers.apply {
        request.headers.forEach {
            append(it.first, it.second)
        }
    }
    this.body = request.body  // <-- BUG: Missing contentType() before setBody!
}
\```

## The Bug

According to Ktor documentation  , when sending JSON with `setBody()`, you must explicitly set the content type. The code is missing:

\```kotlin
contentType(ContentType.Application.Json)
\```

## The Fix

**Option 1: Fix in `buildRequest` function (recommended):**
\```kotlin
private fun <T> HttpRequestBuilder.buildRequest(
    credentials: UserCredentials?,
    request: MatrixHttpClient.HttpRequest<T>
) {
    val host =
        request.baseUrl ?: credentials?.homeServer?.value ?: throw Error()
    this.url("$host${request.path}")
    this.method = when (request.method) {
        Method.GET -> HttpMethod.Get
        Method.POST -> HttpMethod.Post
        Method.DELETE -> HttpMethod.Delete
        Method.PUT -> HttpMethod.Put
    }
    this.headers.apply {
        request.headers.forEach {
            append(it.first, it.second)
        }
    }
    // ADD THIS LINE for POST/PUT requests with body:
    if (request.body != null) {
        contentType(ContentType.Application.Json)
    }
    this.body = request.body
}
\```

**Option 2: Fix in `KtorMatrixHttpClientFactory.kt` (global fix):**
\```kotlin
override fun create(jsonInstance: Json): MatrixHttpClient {
    val client = HttpClient {
        install(ContentNegotiation) {
            json(jsonInstance)
        }
        defaultRequest {
            contentType(ContentType.Application.Json)  // ADD THIS
        }
        expectSuccess = true
        if (includeLogging) {
            install(Logging) {
                logger = Logger.SIMPLE
                level = LogLevel.ALL
            }
        }
    }
    return KtorMatrixHttpClient(client, credentialsStore)
}
\```

## Where to Report

- **File:** `matrix/matrix-http-ktor/src/main/kotlin/app/dapk/st/matrix/http/ktor/internal/KtorMatrixHttpClient.kt`
- **Lines:** 68-85 (the `buildRequest` function)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions