Vapor 4: How to get a String out of the body of a PUT-request?

Hi,

one more Vapor 4 question today:

I want to handle PUT-requests with my Vapor 4 app. Currently I have this code:

routes.swift:

func routes(_ app: Application) throws {
    let geoJSONController = GeoJSONController()
    
    …

    app.put("MapEditorBackend", ":GeoJSONID", use: geoJSONController.put)

    …
}

GeoJSONController.swift:

struct GeoJSONController {
    …
    
    func put(req: Request) throws -> EventLoopFuture<HTTPStatus> {
        let fileContent = "test" // try req.content
        return GeoJSON.find(req.parameters.get("GeoJSONID"), on: req.db)
            .unwrap(or: Abort(.notFound))
            .map {
                try? fileContent.writeToFile(text: fileContent, $0.id!.uuidString)
            }
            .transform(to: .ok)
    }
    
    …
}

and (just for reference)

String+writeToFile.swift:

extension String {
    func writeToFile(
        text: String,
        _ fileName: String,
        folder: String = "Resources/json"
    ) throws {
        let directory = DirectoryConfiguration.detect()
        let fileURL = URL(fileURLWithPath: directory.workingDirectory)
            .appendingPathComponent(folder, isDirectory: true)
            .appendingPathComponent(fileName, isDirectory: false)

        try text.write(to: fileURL, atomically: false, encoding: .utf8)
    }
}

Currently this code writes "test" to a file named like the UUID from the request path. So far so good. Now I want to write the whole body from the PUT-request to that file.

Looking up Request.content in http://api.vapor.codes/vapor/4.0.0-alpha.1/Vapor/Protocols/ContentContainer.html revealed that this field is of Type ContentContainer. I was searching for a function that returned the body as String but found none. Only decoding stuff. Well, I don't want to decode that JSON I am expecting to get but rather store it instead of "test" into that file. How would I do this?

Thanks in advance,

Lars

Use request.body.string

2 Likes

Works like a charm. The code looks now like this:

    func put(req: Request) throws -> EventLoopFuture<HTTPStatus> {
        let fileContent = req.body.string
        return GeoJSON.find(req.parameters.get("GeoJSONID"), on: req.db)
            .unwrap(or: Abort(.notFound))
            .flatMapThrowing { found in
                try fileContent?.writeToFile(found.id!.uuidString)
                
                return .ok
            }.flatMapErrorThrowing { error in
                throw Abort(.internalServerError)
            }
    }

and

extension String {
    func writeToFile(
        _ fileName: String,
        folder: String = "Resources/json"
    ) throws {
        let directory = DirectoryConfiguration.detect()
        let fileURL = URL(fileURLWithPath: directory.workingDirectory)
            .appendingPathComponent(folder, isDirectory: true)
            .appendingPathComponent(fileName, isDirectory: false)

        try self.write(to: fileURL, atomically: false, encoding: .utf8)
    }
}

Thanks a lot again!