Unable to acquire ID for POST of Content-Type: Multipart/form-data to Postgre DB via Fluent

79 views Asked by At

Environment: MacOS 13.5.1 Vapor 4.77 Scenario: Attempting to post:

{"title":"String", "description":"String", "Info":"Data"} to a Postgre DB via Vapor version 4.77.

In this case, I'm using application/JSON for info. But Info could also be an image/png.

Problem: Fluent refuses to auto-generate the ID and hence, I'm getting an error.

Here's the server package:

dependencies: [
         //  A server-side Swift web framework.
         .package(url: "https://github.com/vapor/vapor.git", from: "4.77.1"),
         //  An ORM for SQL and NoSQL databases.
         .package(url: "https://github.com/vapor/fluent.git", from: "4.8.0"),
         //  Fluent driver for Postgres.
         .package(url: "https://github.com/vapor/fluent-postgres-driver.git", from: "2.7.2"),
         .package(url: "https://github.com/vapor/multipart-kit.git", from: "4.5.4"),
     ],

Here's a code snippet from the client, building the URLRequest body via multipart/form-data context-type:

// ...
let title = "Frederick C. Lee"
let description = "Mother had a feeling, I might be too appealing."
    
var body = Data()
let boundary = "Boundary-\(UUID().uuidString)"
    
// Construct request
var request = URLRequest(url: serverURL)
request.httpMethod = "POST"
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
    
// Two boundaries: 1) Country Name and 2) Country Info (Data)
// Note: the multiple '\r\n' is necessary syntax.
    
// 1) Title:
body.append("--\(boundary)\r\n".data(using: .utf8)!)
body.append("Content-Disposition: form-data; name=\"title\"\r\n".data(using: .utf8)!)
body.append("Content-Type: text/plain\r\n\r\n".data(using: .utf8)!)
body.append("\(title)\r\n".data(using: .utf8)!)
// -----------------
// 2) Description
body.append("--\(boundary)\r\n".data(using: .utf8)!)
body.append("Content-Disposition: form-data; name=\"description\"\r\n".data(using: .utf8)!)
body.append("Content-Type: text/plain\r\n\r\n".data(using: .utf8)!)
body.append("\(description)\r\n".data(using: .utf8)!)
// -----------------
// 3) Info (with Data)
body.append("--\(boundary)\r\n".data(using: .utf8)!)
body.append("Content-Disposition: form-data; name=\"info\"\r\n".data(using: .utf8)!)
body.append("Content-Type: application/json\r\n\r\n".data(using: .utf8)!) // Assuming binary data
body.append(infoData!) // Append your actual Data here
body.append("\r\n".data(using: .utf8)!)
    
// Append the final boundary
body.append("--\(boundary)--\r\n".data(using: .utf8)!)
request.httpBody = body
return request
}

The model:

import Fluent
import Vapor
    
final class TurkeyGizzard: Model, Content {
    static let schema = "turkeygizzard"
    
    @ID(key: .id)
    var id: UUID?
    
    @Field(key: "title")
    var title: String
    
    @Field(key: "description")
    var description: String
    
    @Field(key: "info")
    var info: Data?
    
    init() {}
    
    init(title: String, description: String, info: Data) {
         self.id = UUID()
         self.title = title
         self.info = info
    }
}

Here's the Migration:

struct CreateTurkeyGizzards: AsyncMigration {
    func prepare(on database: FluentKit.Database) async throws {
        try await database.schema("turkeygizzard")
            .id()
            .field("title", .string)
            .field("description", .string)
            .create()
    }

    func revert(on database: FluentKit.Database) async throws {
        try await database.schema("turkeygizzard").delete()
    }
}

Initially, I tried to let Fluent generate the ID for me. But that didn't work, so I created a new self.id via initialization.

But I still get the following run error:

Response String: {"error":true,"reason":"Value required for key at path 'id'. No value associated with key "id"."}

I thought Fluent could auto-generate an ID.

Any remedy?

**Note:** I'll try without the Fluent dependency and work directly with persistent storage. Less hassle.

0

There are 0 answers