安装: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. thunk函数

    1.函数参数求值的策略 a.传值策略(c语言) 传值策略就是在进入函数体之前将 参数计算之后 将参数的值传入到函数体之中. let x = 8 f(x + 1)//参数为 f(9)//传进去的值实际上 ...

  2. Linux系统——日志文件

    日志文件的分类 (1)内核及系统日志 由系统服务rsyslog管理,根据去主配置文件/etc/rsyslog.conf中的设置决定将内核消息及各种系统程序消息记录到什么位置. /etc/rsyslog ...

  3. GIt-远程仓库(特性)

    本人拜读了廖雪峰老师关于Git的讲述后整理所得 上一节讲的Git在一个仓库中对于文件进行基本管理和这种和SVN的功能类似, 如果只是在一个仓库里管理文件历史,Git和SVN真没啥区别,并没有体现出Gi ...

  4. cdoj1638 红藕香残玉簟秋,轻解罗裳,独上兰舟。

    地址:http://acm.uestc.edu.cn/#/problem/show/1638 题目: 红藕香残玉簟秋,轻解罗裳,独上兰舟. Time Limit: 4000/2000MS (Java/ ...

  5. POJ - 1511 - 两次SPFA

    这道题也算是一道模板题,但是第一次用优先队列迪杰斯特拉就T了.1e6的数据量,给了8s,网上其他题解中说要用SPFA. 题意:N个点的带权有向图.每次都从1出发,要到达其余没有被访问过的一个点(发传单 ...

  6. mvc结合web应用实例分析

    Mvc的web应用实例分析 Login.jsp——视图部分的输入文件success.jsp——视图部分的输出文件failure.jsp——视图部分的输出文件LoginBean.java——模型部分Lo ...

  7. eclipse中添加tomcat ServerName 无法输入

    Eclipse的开发过程中,无法从以下方式,添加Tomcat服务器.  其中ServerName是被置为灰色的,无法编辑.  如何解决 1.  关闭Eclipse 2.  打开WorkSpace所在的 ...

  8. tomcat高并发配置调优

    最近部署的tomcat,里面放了一个apk提供给测试人员测试,而有一天压测的时候,他们一致反馈下载不了,结果查看日志才发现如下错误: [html] view plain copy INFO: Maxi ...

  9. 【c++ primer, 5e】函数指针

    简单的示例: #include <iostream> using namespace std; int sum(int x, int y) { return x + y; } int ma ...

  10. 【Thinking in Java, 4e】访问权限控制

    [包:库单元] 编译单元的概念. 一个.java文件就是一个编译单元,一个编译单元只能有一个public类,编译单元中的非public类一般是用于为public类提供支持的,这些类在包外不可见. im ...