zoukankan      html  css  js  c++  java
  • 全--教程API, gem 'rest-client'(用于发简单请求); 请求测试;

    安装: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
  • 相关阅读:
    Coding 账户与 本地 Git 客户端的配置
    leetcode_sort-list
    leetcode_insertion-sort-list
    leetcode_move-zeroes
    search-insert-position
    leetcode_remove-nth-node-from-end-of-list
    leetcode_queue-reconstruction-by-height
    leetcode_valid-parentheses
    leetcode_swap-nodes-in-pairs
    20201115-东北师范大学-助教-周总结-第9次
  • 原文地址:https://www.cnblogs.com/chentianwei/p/9270295.html
Copyright © 2011-2022 走看看