Search code examples
ajaxrestgrails

Sending files as strings in post request stops params being parsed


I have created a grails web app that is used as a member login so people can track and change their information.

As part of this when creating an account, files are sent to a controller from an ajax request. The string content of the file is what is sent.

Checking the network traffic in chrome shows that the data is sent correctly.

There are 3 files sent in the request and each is the same file, sent in the same way.

The problem is that when the third file is sent, the parameters are not parsed to the parameter map when it reaches the controller action. They are available at request.reader.text. If only 2 of the files are sent then it works perfectly and the params are available.

This did used to work and I have reverted the changes I had done in UrlMappings but still no luck.

I have also increased the maxRequestSize but I think the request size is only approx 18Kb so this shouldn't be a problem.

Another thing is that I have edit functionality for the user using a PUT request. When doing the same thing there it all works fine. The ajax requests are the same, one just uses PUT and the other POST.

Below is my post ajax request and my UrlMappings.groovy. If you would find anymore information useful please let me know.

var request = jQuery.ajax({
        type: 'POST',
        data: {
            firstName: $("input[name='" + _selectors.firstNameSelector + "']").val(),
            lastName: $("input[name='" + _selectors.lastNameSelector + "']").val(),
            dob: $("input[name='" + _selectors.dobSelector + "']").val(),
            email: $("input[name='" + _selectors.emailSelector + "']").val(),
            mobile: $("input[name='" + _selectors.mobileSelector + "']").val(),
            addressLine1: $("input[name='" + _selectors.addressLine1Selector + "']").val(),
            addressLine2: $("input[name='" + _selectors.addressLine2Selector + "']").val(),
            townCity: $("input[name='" + _selectors.townCitySelector + "']").val(),
            postcode: $("input[name='" + _selectors.postcodeSelector + "']").val(),
            emergencyName: $("input[name='" + _selectors.emergencyNameSelector + "']").val(),
            emergencyNumber: $("input[name='" + _selectors.emergencyNumberSelector + "']").val(),
            emergencyEmail: $("input[name='" + _selectors.emergencyEmailSelector + "']").val(),
            emergencyRelationship: $("input[name='" + _selectors.emergencyRelationshipSelector + "']").val(),
            emergencyAddressLine1: $("input[name='" + _selectors.emergencyAddressLine1Selector + "']").val(),
            emergencyAddressLine2: $("input[name='" + _selectors.emergencyAddressLine2Selector + "']").val(),
            emergencyTownCity: $("input[name='" + _selectors.emergencyTownCitySelector + "']").val(),
            emergencyPostcode: $("input[name='" + _selectors.emergencyPostcodeSelector + "']").val(),
            username: $("input[name='" + _selectors.usernameSelector + "']").val(),
            role: $("#role option:selected").val(),
            dateOfJoining: $("input[name='" + _selectors.dateOfJoiningSelector + "']").val(),
            membershipFile: files[_selectors.membershipFileSelector],
            privacyFile: files[_selectors.privacyFileSelector],
            medicalHistories: _self.collectMedicalHistories(),
            classes: _self.collectAttendedClasses(),
            grades: _self.collectGrades(),
            insurances: _self.collectInsurances()
        },
        url: _accountsUrl.addUser,
        success: _self.resolveUserAddSuccessResponse,
        error: _self.showUserAddErrors
 });

UrlMappings.groovy

    "/api/$controller/$action/$id" {
        namespace = "api"
        constraints {}
    }

    "/api/admin/$controller" {
        namespace = "api"
        action = [
                GET   : "get", // show - get one item by id
                POST  : "post", // create - by submitting full content
        ]
    }

    "/api/admin/$controller/$id" {
        namespace = "api"
        action = [
                GET   : "get", // show - get one item by id
                PUT   : "put",  // update - by submitting full content
                DELETE: "delete", // delete - delete one item by id
                POST  : "post", // create - by submitting full content
        ]
    }

Solution

  • Having read about a bit more, you can not always rely on information being parsed into params. It should only really be used for url parameters.

    I decided instead to try get it working with request.JSON as this is a better method of retrieving the information from the body of a post request.

    Just changing the Content-Type to application/json didn’t work. I also had to do

    data: JSON.stringify({...})
    

    in the ajax request. This finally got it working!