¿Cómo invocar el método HTTP POST sobre SSL en ruby?

Así que aquí está la solicitud usando curl:

curl -XPOST -H content-type:application/json -d "{\"credentials\":{\"username\":\"username\",\"key\":\"key\"}}" https://auth.api.rackspacecloud.com/v1.1/auth 

He estado tratando de hacer esta misma solicitud usando ruby, pero parece que no puedo hacer que funcione.

Probé un par de bibliotecas también, pero no puedo hacer que funcione. Esto es lo que tengo hasta ahora:

 uri = URI.parse("https://auth.api.rackspacecloud.com") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true http.verify_mode = OpenSSL::SSL::VERIFY_NONE request = Net::HTTP::Post.new("/v1.1/auth") request.set_form_data({'credentials' => {'username' => 'username', 'key' => 'key'}}) response = http.request(request) 

Recibo un error de tipo de medios 415 no compatible.

Estás cerca, pero no del todo allí. Pruebe algo como esto en su lugar:

 uri = URI.parse("https://auth.api.rackspacecloud.com") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true http.verify_mode = OpenSSL::SSL::VERIFY_NONE request = Net::HTTP::Post.new("/v1.1/auth") request.add_field('Content-Type', 'application/json') request.body = {'credentials' => {'username' => 'username', 'key' => 'key'}} response = http.request(request) 

Esto configurará el encabezado de tipo de contenido, así como también publicará el JSON en el cuerpo, en lugar de los datos del formulario como lo tenía su código. Con las credenciales de muestra, todavía falla, pero sospecho que debería funcionar con datos reales allí.

Hay una muy buena explicación de cómo hacer una solicitud JSON POST con Net :: HTTP en este enlace .

Yo recomendaría usar una biblioteca como HTTParty . Está bien documentado, puedes configurar tu clase de la siguiente manera:

 class RackSpaceClient include HTTParty base_uri "https://auth.api.rackspacecloud.com/" format :json headers 'Accept' => 'application/json' #methods to do whatever end 

Parece que la principal diferencia entre el código de Ruby que colocó allí y la solicitud de curl, es que la solicitud curl es POSTing JSON (application / json de tipo de contenido) al punto final, mientras que request.set_form_data va a enviar un formulario en el cuerpo de la solicitud POST (application-type application / x-www-form-urlencoded). Debe asegurarse de que el contenido en ambos sentidos sea del tipo application / json.

Todos los demás son demasiado largos aquí hay UN SOLO LINER :

 Net::HTTP.start('auth.api.rackspacecloud.com', :use_ssl => true).post( '/v1.1/auth', {:credentials => {:username => "username",:key => "key"}}.to_json, initheader={'Content-Type' => 'application/json'} ) 

* to_json needs require 'json'


O si quieres

  • NO verifica los hosts
  • ser más legible
  • asegúrese de que la conexión esté cerrada una vez que haya terminado

entonces:

 ssl_opts={:use_ssl => true, :verify_mode => OpenSSL::SSL::VERIFY_NONE} Net::HTTP.start('auth.api.rackspacecloud.com', ssl_opts) { |secure_connection| secure_connection.post( '/v1.1/auth', {:credentials => {:username => "username",:key => "key"}}.to_json, initheader={'Content-Type' => 'application/json'} ) } 

En caso de que sea difícil recordar qué parámetros van a dónde:

  • Las opciones SSL son por conexión, así que las especificas al abrir la conexión.
  • Puede reutilizar la conexión para múltiples llamadas REST a la misma URL base. Piense en seguridad hilo, por supuesto.
  • El encabezado es un “encabezado de solicitud” y, por lo tanto, se especifica por solicitud. Es decir, en llamadas para get / post / patch / ...
  • HTTP.start() : crea un nuevo objeto Net :: HTTP y luego abre la conexión TCP y la sesión HTTP.
  • HTTP.new() : crea un nuevo objeto Net :: HTTP sin abrir una conexión TCP o una sesión HTTP.

Otro ejemplo:

 #!/usr/bin/ruby require 'net/http' require 'json' require 'uri' full_url = "http://" + options[:artifactory_url] + "/" + "api/build/promote/" + options[:build] puts "Artifactory url: #{full_url}" data = { status: "staged", comment: "Tested on all target platforms.", ciUser: "builder", #timestamp: "ISO8601", dryRun: false, targetRepo: "#{options[:target]}", copy: true, artifacts: true, dependencies: false, failFast: true, } uri = URI.parse(full_url) headers = {'Content-Type' => "application/json", 'Accept-Encoding'=> "gzip,deflate",'Accept' => "application/json" } http = Net::HTTP.new(uri.host, uri.port) request = Net::HTTP::Post.new(uri.request_uri, headers) request.basic_auth(options[:user], options[:password]) request.body = data.to_json response = http.request(request) puts response.code puts response.body