安装:rest-client4400✨
gem install rest-client

一个简单的HTTP和REST client for Ruby.

可以用它来发HTTP请求

基本用法:

require 'rest-client'

RestClient.get(url, headers={})

RestClient.post(url, payload, headers={})


什么是API

Application Programming Interface: 程序和程序的接口,定义接口叫什么名字,要传什么参数进去,它会回传什么东西出来,可能回发生的errors等等。

在写Ruby程序的时候,使用library库的方法,这时候API就是method的名字,参数,回传值等等。

对Web应用来说,API就是在定义网址URL的样子,请求的HTTP方法是什么,传什么参数过去,返回什么资料格式。

常用的就是JSON, XML。


JSON格式的转化,to_json和parse

> require 'json'

 => true
> { :id => 123, :name => "foobar" }.to_json
 => "{\"id\":123,\"name\":\"foobar\"}"
> JSON.parse( "{\"id\":123,\"name\":\"foobar\"}" )
 => {"id"=>123, "name"=>"foobar"}

使用聚合数据网

  1. 注册聚合数据网,选择一类数据并自动得到它的appAPI:
  2. 登陆这个api的网站https://www.juhe.cn/docs/api/id/39 ,下载示例代码。
  3. 使用请求示例:http://v.juhe.cn/weather/citys?key=您申请的KEY
  4. irb
require 'rest-client'
require 'json'
response = RestClient.get "http://v.juhe.cn/weather/citys?key=您申请的KEY
"
data = JSON.parse(response.body)#得到hash格式的数据集合
data.keys#得到keys
data["result"][0]#得到具体数据。

bundle exec

在当前的bundle中,执行一个script


Rake(software)维基百科

rake是一个软件task管理和bulid automation tool.It allows the user to specify tasks and describe dependencies as well as to group tasks in a namespace.

https://ruby.github.io/rake/

⚠️ruby新版已经放弃使用rake了,这里就不学习了。



在“ 离线保存的全栈文件/我的练习/webapi练习/api_exercise”目录建立本教程app.

在rails上获得聚合网的天气API,

重点1:建立lib/tasks/dev.rake文件,建立一个script

# 编写任务script 执行bundle exec rake dev:fetch_city
namespace :dev do
  task :fetch_city => :environment do
    puts "Fetch city data..."
    # 从聚合数据网上,得到api钥匙,然后下载json格式的数据。
    response = RestClient.get "http://v.juhe.cn/weather/citys?key=214b163d003a4799cb76359b6d30b7de"
    # 转化为hash格式
    data = JSON.parse(response.body)
    # 把数据存入创建的City数据库中。
    data["result"].each do |c|
      existing_city = City.find_by(juhe_id: c["id"])
      if existing_city.nil?
        City.create!(juhe_id: c["id"], province: c["province"], city: c["city"], district: c["district"])
      end
    end
 
    puts "Total: #{City.count} cities"
  end
end
 

重点2: 保护API key

  1. 新增config/juhe.yml , 设置development环境和production环境的api_key:"XXX"
  2. 然后在application.rb中的Applicaiton类中设置一个常量JUHE_CONFIG,用于存储不同程序环境下的api_key。
  3. JUHE_CONFIG = Rails.application.config_for(:juhe)
  4. 把程序中的api_key换成 JUHE_CONFIG["api_key"]
  5. 把juhe.yml标记在.gitignorre中: /config/juhe.yml, 不进行版本控制,保护密匙。
  6. 惯例新增一个juhe.yml.example,让同事看到这个样例。
⚠️ YAML格式是缩进的。区分数字和字符串,hash的key用字串表示。

根据火车train 的API,建立查询和订票系统:

要实作一个订票系统 API 服务器,可以提供给手机 iOS, Android 应用程式,或是一个开放平台给别的开发者串接使用。

重点1:

routes.rb的设置:

  namespace :api, :default => {:format => :json} do
    namespace :v1 do
      get "/trains" => 'trains#index', :as => :trains
      get "/trains/:train_number" => 'trains#show', :as => :train

as用来产生路由地址的方法

api_v1_trains_url

会请求http://localhost:4000/api/v1/trains 这个网页。

api_vi_train_url(train.number)

会请求转到http://localhost:4000/api/v1/trains/0822 ,假设train.number是“0822”

重点2:

render :json => {变量}

会把变量转成 JSON 字串输出。这里不需要准备 View .erb 档案。
因为这两个 API 都是用 HTTP GET 读取,我们可以直接打开浏览器,浏览 http://localhost:3000/api/v1/trains 就是用 GET 读取资料

例子:

在reservations_controller.rb#create方法中:

if @reservation.save

render :json => {...}

else

render :json => {:message => "订票失败", :errors => @reservation.errors }, status =>400

重点3:

--no--assets选项的意思,不生成相关javascritps和styleshees的对应文件。

rails g controller api::v1::reservations --no-assets

不生产:

 invoke  assets
      invoke    coffee
      create      app/assets/javascripts/api/v1/reservations.coffee
      invoke    scss
      create      app/assets/stylesheets/api/v1/reservations.scss

❌1

报告错误, InvalidAuthenticity 指未通过真实性验证。

ActionController::InvalidAuthenticityToken in Api::V1::ReservationsController#create

在create方法中,需要验证validations。猜测可能是验证的问题。

打开rails console,输入Reservation.count , 提示错误❌:

ArgumentError (Unknown validator: 'ScopeValidator')

发现验证格式写错误了:

❌validates :seat_number, :scope => :train_id , uniqueness: true ❌

✅validates :seat_number, uniqueness: {:scope => :train_id}

或 validates_uniqueness_of :seat_number, :scope => :train_id

但仍然未解决第一个❌:不过不影响在控制台,模拟create方法,✅生产reservation记录。

另外,destroy,update都会报告类似❌。

✅于是复制问题到谷歌和stackoverflow, 找到完美问题原因:

解决办法:在api控制器上加上 skip_before_action :verify_authenticity_token

我已经让ApiController直接继承ActionController::Base

class ApiController < ActionController::Base

但还是不能逃脱检查 伪信息和敏感请求参数。

Rails API

有一个模块RequestForgeryProtection,内有2个类方法:

第一个: 

class ApplicationController < ActionController::Base
protect_from_forgery
end

⚠️,GET和HEAD request不会被检查

⚠️,有vaild options:

:only/:except

:if/:unless

:with => :null_session/:reset_session/:exception

第二个:

关掉虚假信息的请求保护

skip_before_action :verify_authenticity_token 

train.reservations.pluck(:seat_number)

得到关联对象集合的某个属性的集合: 相当于查询method

Reservation.joins(:trains).where("trains.id == *** ").select(:seat_number)

或者 纯SQL

select reservations.seat_number FROM reservations inner JOIN trains ON  trains.id == reservations.train_id where train.id == **


给火车订票系统,添加用户,用户可以订票

重点1

给user增加一个API key ,作为唯一识别码。

    add_column :users, :authenication_token, :string

add_index :users, :authenication_token, :unique => true

在user.rb中,添加self.authentication_token = Devise.friendly_token

一个随机的20个字母的字符串(见gem 文档)

唯一的识别码,

  • 安全性,乱数产生的强度比密码高,甚至可以设计有效时间
  • 独立性,使用者改密码不会影响 api key,这样客户端就不需要重新设定过

如何写用户认证API:

https://github.com/plataformatec/devise/wiki/How-To:-Simple-Token-Authentication-Example (已过期,有可选的链接)

可选:

devise_token_auth(2450✨) 2018-7有更新

Token ,基于Rails JSON APIs的验证的token。

可以和devise一起用,支持使用Devise进行email验证,以及用户注册,登入,密码相关修改。


request.format = :json

增加一个views/api/v1/trains/show.json.jbuilder

在controllers/api/v1/trains_controller.rb中增加show方法。

⚠️写网址的时候务必加上.json

http://localhost:4000/api/v1/trains/0603.json

否则无法找到show.json.jbuilder模版,因为默认是text/html。

或者在controller中加上:

  # before_action :set_default_format
  #
  # def set_default_format
  #   request.format = :json
  # end

分析:get "/trains/:train_number" => 'trains#show', :as => :train

/trains/:train_number 是指URL, 类似user/:id

⚠️加上冒号:,是指具体的记录的属性名称。

as: :train是用于生成helper链接 ,train_url(train.number)


分页功能:

加入gem 'kaminari'

rails g kaminari:config 然后设置默认每页数量,重启服务器。

在控制器@trains = Train.order(:number).page(params[:page])

在views:

# 加入分页功能
json.meta1 do
  json.current_page @trains.current_page
  json.total_pages @trains.total_pages
  json.per_page @trains.limit_value
  json.total_trains Train.count
 
  if @trains.current_page == @trains.total_pages
    json.next_url nil # 最后一页就没有下一页了
  else
    json.next_url api_v1_trains_url(page: @trains.next_page )
  end
 
  if @trains.current_page == 1
    json.previous_url nil # 第一页就没有上一页
  else
    json.previous_url api_v1_trains_url( :page => @trains.prev_page )
  end
end

给Train加一个图片

has_one_attached :image

上传:

train.logo.attach(io: File.open("/Users/chentianwei/Desktop/bose.jpg"),

filename: "bose.jpg",

content_type: "image/jpg")


合并分支 :

git checkout master

git merge train_book

完成后上传到git. https://github.com/chentianwei411


远程仓库如果变化了,本地就不能git push 了,需要先git fetch,但我似乎fetch不下来?

学习git 的链接:

https://git-scm.com/


对API 进行测试

之前的博客:https://www.cnblogs.com/chentianwei/p/9060522.html, http://www.cnblogs.com/chentianwei/p/9124505.html

加上gem 'rspec-rails'

10133  git checkout -b test
10134  bundle
10135  rails g rspec:install
10136  git add .
10137  git commit -m "add Rspec"
10138  git push
10139  git push --set-upstream origin test   #在远程上建立一个分支,等待合并。

Web API 测试的重点是:

  1. 检查回传的 HTTP 状态码
  2. 检查回传的 JSON
  3. 检查资料真的有被新建、修改或删除

对API测试,是请求测试,即对请求的回复结果的判断是否是预期判断:

使用rails g rspec:request XXX 快速生成

spec/requests/auth_spec.rb

RSpec.describe "API_V1::Auth", :type => :request do

HTTPVerb 路径, params:{hash参数}

expect(response).to have_http_status(响应数字)

expect(response.body).to eq({hash参数}.to_json)

end

一个例子:

重点1:

response的网页状态码可以在controller中设置,如:

def signup

...
render :json => { :message => "Failed", :errors => user.errors }, :status => 400
当符合条件后,会返回response的status就是400

全--教程API, gem 'rest-client'(用于发简单请求); 请求测试;的更多相关文章

  1. Docker最全教程——从理论到实战(六)

    托管到腾讯云容器服务 托管到腾讯云容器服务,我们的公众号“magiccodes”已经发布了相关的录屏教程,大家可以结合本篇教程一起查阅.   自建还是托管? 在开始之前,我们先来讨论一个问题——是自建 ...

  2. 800元组装一台3D打印机全教程流程

    我最近正好要组装一台新的reprap的kossel delta型开源3d打印机,这台机器性价比非常高,具有速度快,静音,三臂并联结构,扩展性强,便宜的特点.图纸啥的都有,只是用到mega2560和ra ...

  3. Docker最全教程之使用Tencent Hub来完成CI(九)

    使用Tencent Hub来完成CI 关于Tencent Hub Tencent Hub是腾讯出品的DevOps服务.主要提供多存储格式的版本管理,支持Docker Image.Binary.Helm ...

  4. Docker最全教程——从理论到实战(八)

    在本系列教程中,笔者希望将必要的知识点围绕理论.流程(工作流程).方法.实践来进行讲解,而不是单纯的为讲解知识点而进行讲解.也就是说,笔者希望能够让大家将理论.知识.思想和指导应用到工作的实际场景和实 ...

  5. 全屏API接口

    HTML5的诞生给我们提供了很多精彩的JavaScript和HTML新功能和新特征.有些新特征我们已知多年并大量的使用,而另外一些主要是用在前沿的手机移动技术上,或者桌面应用中起辅助作用.不管这些HT ...

  6. 800元组装一台3D打印机全教程流程-零件清单

    继前面的教程800元组装一台3D打印机全教程流程 k800是一台根据kosselmini改进的低成本3d打印机,通过改变设计,降低了成本,但损失较少性能,取得性价比. 主要改动是:底部支架改为-> ...

  7. Docker最全教程之使用Node.js搭建团队技术文档站(二十三)

    前言 各种编程语言均有其优势和生态,有兴趣的朋友完全可以涉猎多门语言.在平常的工作之中,也可以尝试选择相对适合的编程语言来完成相关的工作. 在团队技术文档站搭建这块,笔者尝试了许多框架,最终还是选择了 ...

  8. 在vs2017和vs2019下发布应用之Windows程序打包-附图标修改和默认安装路径定义全教程

    title: 在vs2017和vs2019下发布应用之Windows程序打包-附图标修改和默认安装路径定义全教程 date: 2020-04-25 sidebarDepth: 2 tags: wind ...

  9. 分布式链路追踪之Spring Cloud Sleuth+Zipkin最全教程!

    大家好,我是不才陈某~ 这是<Spring Cloud 进阶>第九篇文章,往期文章如下: 五十五张图告诉你微服务的灵魂摆渡者Nacos究竟有多强? openFeign夺命连环9问,这谁受得 ...

随机推荐

  1. mysql相关配置

    http://www.cnblogs.com/cnblogsfans/archive/2009/09/21/1570942.html http://www.jb51.net/article/31902 ...

  2. jmeter接口测试实战

    请求方法:get/post 接口请求地址:http://172.22.24.26:8080/fundhouse/external/getdata?name=xxxx &fund_udid=35 ...

  3. java反射之构造方法(三)

    一. 1. 二.获取类的构造方法信息. ######################################################################## 三.

  4. HackerRank - candies 【贪心】

    HackerRank - candies [贪心] Description Alice is a kindergarten teacher. She wants to give some candie ...

  5. 论文笔记:OverFeat: Integrated Recognition, Localization and Detection using Convolutional Networks

    2014 ICLR 纽约大学 LeCun团队 Pierre Sermanet, David Eigen, Xiang Zhang, Michael Mathieu, Rob Fergus, Yann ...

  6. JVM内存区域划分Eden Space\Survivor Space\Tenured Gen\Perm Gen

    JVM区域分heap区和非heap区. 1)heap区:Eden Space(伊甸园),Survivor Space(幸存者区),Tenured Gen(老年代-养老区). 2)非heap区:Code ...

  7. Java Vertor详细介绍和使用示例

    ①对Vector有个整体认识 Vector是向量类,继承于AbstractList,实现了List,RandomAccess,Clonable这些接口. Vector继承于AbstractList,实 ...

  8. Django学习笔记之Django Form表单详解

    知识预览 构建一个表单 在Django 中构建一个表单 Django Form 类详解 使用表单模板 回到顶部 构建一个表单 假设你想在你的网站上创建一个简单的表单,以获得用户的名字.你需要类似这样的 ...

  9. Thinkphp5.0实战开发二------自动生成目录结构

    序言 ThinkPHP5.0 具备自动创建功能,可以用来自动生成需要的模块及目录结构和文件等,自动生成主要调用\think\Build 类库.ThinkPHP5.0中模块文件夹在application ...

  10. ArrayList原理分析(重点在于扩容)

    首先,ArrayList定义只定义类两个私有属性: /** * The array buffer into which the elements of the ArrayList are stored ...