1

I have created REST Api in Ruby on Sinatra platform. I am testing the service with Postman and whatever JSON form I try to POST I keep getting an error 400 Invalid JSON SUCKER. The error is defined on the back end in case of invalid JSON form. Please take a look at the back end and tell me what am I doing wrong.

I have to mention that GET method works with Postman and cURL from the command line while POST works only if I use it with cURL but NOT in POSTMAN.

#server.rb
require 'sinatra'
require 'mongoid'
require 'sinatra/namespace'
require 'sinatra/base'
#require 'json'

before do
   content_type :json    
   headers 'Access-Control-Allow-Origin' => '*', 
            'Access-Control-Allow-Methods' => ['OPTIONS', 'GET', 'POST', 'PATCH']  
end

#load database config
Mongoid.load! "mongoid.config"

#Class Company 
class Company
  include Mongoid::Document


  field :compid, type: String
  field :name, type: String
  field :address, type: String
  field :city, type: String


#  validates :compid, presence: true
#  validates :name, presence: true

  index({ compid:1 }, { unique: true, name: "compid_index" })
  index({ name: 'text' })

  scope :name, -> (name) { where(name: /^#{name}/) } # this could be changed to /^#{title}/i to make case insensitive searcg =end
  scope :compid, -> (compid) { where(compid: compid) }
end

#Serializers

class Serializer
  def initialize(company)
    @company = company
  end

  def as_json(*)
    data ={
      id:@company.compid.to_s,
      name:@company.name,
      address:@company.address,
      city:@company.city,
    }
    data[:errors] = @company.errors if@company.errors.any?
    data
  end
end

# Endpoints

  get '/' do  
   'List of all Companies'
  end

namespace '/api/v1' do

  before do
    content_type 'application/json'
  end

  helpers do
    def base_url
      @base_url ||= "#{request.env['rack.url_scheme']}://{request.env['HTTP_HOST']}"
    end

  def json_params
      begin
        JSON.parse(request.body.read)
      rescue
        halt 400, { message:'Invalid JSON' }.to_json
      end
    end
  end

  get '/companies' do
    companies = Company.all

    [ :name, :compid,].each do |filter|
       companies = companies.send(filter, params[filter]) if params[filter]
    end

#put it through the serializer not to get all te atributes
     companies.map { |company| Serializer.new(company) }.to_json
  end

  get '/companies/:compid' do |compid|  #get the details about the company by searching with compid
    company = Company.where(compid: compid).first
    halt(404, { message:'Company Not Found'}.to_json) unless company 
    Serializer.new(company).to_json

  end  

post '/companies' do
    company = Company.new(json_params)
    if company.save
      response.headers['Location'] = "#{base_url}/api/v1/companies{company.copmid}" # "{company.id}" 
      status 201

    else
      status 422
      body Serializer.new(company).to_json
    end
  end

The data that I GET with the Postman looks like this:

[{"id":"5a1271f7943e8a0f5fd76008","name":"The Power Of Habit","address":"Charles Duhigg Vej","city":"Viborg"}]

I have tried to POST data in various forms:

[{"id":"5a1271f79asdd76008","name":"The Power Of Habit","address":"Charles Duhigg Vej","city":"Viborg"}]

{"id":"5a1271f79asdd76008","name":"The Power Of Habit","address":"Charles Duhigg Vej","city":"Viborg"}

[{"compid":"5a1271f79asdd76008","name":"The Power Of Habit","address":"Charles Duhigg Vej","city":"Viborg"}]

{"compid":"5a1271f79asdd76008","name":"The Power Of Habit","address":"Charles Duhigg Vej","city":"Viborg"}
quant
  • 493
  • 9
  • 21
  • If you have a working example with `cURL`, did you know that you can import this directly into postman? Click `File --> Import --> Paste Raw Text`. This should make the correct syntax apparent. – Tom Lord Nov 20 '17 at 10:21
  • I can't import, it is not recognizing the format – quant Nov 20 '17 at 11:08
  • What format? Postman should support any valid `cURL` command, as far as I know. – Tom Lord Nov 20 '17 at 11:09
  • Can you include the working `cURL` command in your question? You may redact any sensitive information, so long as the structure of the command remains intact. – Tom Lord Nov 20 '17 at 11:11
  • curl -i -X POST -H "Content-Type: application/json" -d'{"name":"Samba", "address":"Sambavej", "city":"Samba"}' http://localhost:4567/api/v1/companies – quant Nov 20 '17 at 11:15
  • I get curl: (52) Empty reply from Server and the data is there updated in JSON form – quant Nov 20 '17 at 11:18
  • Put a space between the `-d` and the `'`. Then it imports just fine. – Tom Lord Nov 20 '17 at 12:08
  • Ok, i can POST raw JSON form now with the Postman, but if i choose headers: x-www-form-urlencoded, I got error: There was an error in evaluating the test script: SyntaxError: Unexpected token : the file server.rb is the same, God, I got stuck here – quant Nov 20 '17 at 14:46
  • What is `request.body.read`? Try to debug it. – Tom Lord Nov 20 '17 at 14:59
  • that is here because I cant see any data when I POST with the headers: {'Content-Type': 'application/x-www-form-urlencoded'}, I found something similar here: https://stackoverflow.com/questions/12131763/sinatra-controller-params-method-coming-in-empty-on-json-post-request, but unfortunately i am not sure how to implement it exactly. I am sure that this is the problem on the server side, because POST with the raw data with Postman works. Thanks for help – quant Nov 20 '17 at 18:21

0 Answers0