GitHub实践(txt+pdf+epub+mobi电子书下载)


发布时间:2020-09-24 03:01:02

点击下载

作者:克里斯·道森(Chris Dawson)

出版社:人民邮电出版社

格式: AZW3, DOCX, EPUB, MOBI, PDF, TXT

GitHub实践

GitHub实践试读:

前言

本书说明如何构建软件工具。

如果你经常编写软件,肯定知道这其实是创建工具的过程。软件也是工具。说到底,电子表格只是加减数字的工具,电子游戏只是打发无聊时间的工具。在人们开始编写软件工具之后,我们几乎立即发现,为了顺利写出一开始想写的那个软件,需要有更多的工具来支持。我们把这些支持软件开发的工具(不是常规意义上的软件工具)叫作元工具(meta-tool)。

在软件开发领域,最重要的一个元工具是 Git。这个元工具能帮助软件开发者解决编写软件过程中的复杂问题。使用 Git,软件开发者可以存储程序的快照(如果需要,可以轻易还原快照),还便于与其他程序员协作(这是个相当复杂的问题)。Git 是一种源码管理(Source Code Management,SCM)工具,虽然在此之前有很多 SCM 工具,但是都没像 Git 这样对软件领域产生如此大的影响。目前,Git 在 SCM 工具中处于领先地位。

GitHub 公司及早发现了 Git 的无穷潜力,以 Git 的功能为底层基础,构建了一层 Web 服务。不难想象,GitHub 成功的因素之一是,员工们从一开始就积极跟随潮流,编写大量的元工具。开发元工具要耐得住寂寞,不能急于求成。GitHub 的员工们对这种做事顺序引以为荣,并撰写了大量文章说明了这样做的好处,例如便于新员工融入,工作流程对所有员工都透明。

本书一窥 GitHub 内部使用的工具。GitHub.com 网站本身也是一个元工具,我们会从多个方面讨论 GitHub 服务。具体而言,我们涉及的技术有 GitHub API 及相关的 GitHub 技术、Gollum 维基、静态页面生成工具 Jekyll,以及聊天机器人 Hubot(如果你对这些都不熟悉,不用担心,我们将在不同的章节详细说明)。

我要重申一点,这不是上述几项技术的参考书。这是一本故事书,以叙事的方式描述构建软件元工具的相关过程,期间不只介绍相关的技术,还会说明折中方案、重构的现实意义,以及编写元工具面临的挑战。

编写元工具所需的思维与常规的软件不同。一般来说,元工具是开源的,用法和责任都不同寻常。有人可能认为,与普通用户相比,软件工程师对质量有更高的要求,因为软件不能满足软件开发者的需求时,他们可以改进或派生。编写元工具需要付出更多的精力,因而自动化测试几乎是必备的。开发元工具之前一定要知道这些概念,本书将告诉你如何在构建元工具的过程中运用这些概念。为什么使用API,为什么选择GitHub API

使用 API 支持应用是当下常见的做法,这也是应用开发的发展方向。如今显示设备多种多样,使用 API 能在不同的设备中更好地呈现数据。以远程服务 API 支持的应用,起初可能是运行在 Apple iOS 操作系统中的移动应用。经市场验证之后,如果发现这种商业模式不正确,可以迅速响应变化的需求,为 Android 穿戴设备构建新应用,构建车载应用,或者其他控制台(或非控制台)应用。只要应用能调用远程 API 收发数据,你就能为任何平台构建任何用户界面。

此外,我们自己也可以编写和托管 API。Ruby、Go 和 Java 等流行语言的很多框架都支持使用标准的架构风格(如 REST)构建 API。不想自己构建的话,还可以使用第三方 API。本书专门针对一个第三方 API,即 GitHub API。

为什么是 GitHub API 呢?对构建软件的你来说,基本上离不开 GitHub API,因为你可能就使用 GitHub 管理软件代码。即便不用 GitHub,也有可能使用 Git。而 GitHub API 也能操作 Git,因为它把 Git 的功能抽象成网络编程接口了。

GitHub API 算是我见过设计得最好的 API 了。它是超媒体 API,基本上成功解决了一个棘手问题:让 API 客户端适应 API 的变化。GitHub API 有良好的版本划分,功能完整,而且实现了大多数 Git 功能。GitHub API 由多个结构合理的部分组成,便于构建应用。GitHub API 是个典型,通过它可以学习好的 API 应该怎么设计。本书结构

GitHub API 的功能非常全面,通过它可以访问和修改 Git 仓库中存储的或与之有关的几乎所有数据和元工具。根据 GitHub API 的文档(https://developer.github.com/v3/),我按照字母顺序简要列出了其各部分的作用。● Activity:开发者关注的事件通知● Gists:以编程的方式创建和分享代码片段● Git Data:通过远程 API 访问原始的 Git 数据● Issues:添加和修改工单● Miscellaneous:无法纳入其他分类的 API● Organizations:存取组织成员数据● Pull Requests:一个强大的 API,建构在合并过程之上● Repositories:修改与仓库有关的一切数据● Search:在整个 GitHub 数据库中搜索代码● Users:访问用户数据● Enterprise:企业内部的 GitHub 专用的 API

此外,有些重要的技术在 GitHub API 文档中没有说明。虽然这些技术不是 API 的一部分,但是使用 GitHub 时应该知道。● Jekyll 和“gh-pages”:托管博客和静态文档● Gollum:与仓库关联的维基● Hubot:GitHub 广泛使用的可编程聊天机器人

GitHub 技术栈的各个部分分别在不同的章节介绍(有两个不会介绍,原因如后)。GitHub API 文档是优秀的参考,编写与 GitHub API 通信的应用时会经常查阅。本书的目的则不同,我们将叙述如何使用 GitHub 提供的技术构建应用。这些故事会告诉你使用 GitHub API 时要采取哪些折中措施,有什么注意事项。如果需要,一章可能涵盖多个 API。通常,每一章都尽量专注于一个主要的 API,努力不涉及其他 API,但是大多数章节确实需要涉及别的 API。

下面概述各章的内容。

第 1 章首次介绍如何使用命令行 HTTP 客户端 cURL 访问 API,并说明响应的格式、如何在命令行中解析响应,以及身份验证方式。这是本书唯一没有使用上述技术构建应用的一章。

第 2 章介绍 Gist API、几个命令行工具,以及 Ruby 语言 API 客户端 Octokit。然后,使用 Gist API 构建一个简单的 Ruby 服务器,存储并显示 Gist。

第 3 章说明如何使用 Gollum 命令行工具及相关的 Ruby 库(gem)。Gollum 由 Grit 提供支持,Grit 是一个 C 语言绑定,用于访问 Git 仓库。我们还会说明 Git 存储格式的一些细节,在 Git 仓库中存储大文件的方式,以及如何使用 Git 命令行工具访问这些信息。这一章使用 Gollum 和 Grit 库构建一个图像管理工具,不过它仍是一个常规的 Gollum 维基,可以发布到 GitHub 中。

第 4 章探讨 Search API,然后使用 Python 构建一个 GUI 工具,用于搜索 GitHub 中的仓库。

第 5 章介绍 GitHub API 中一个相对新的部分,这一部分用于描述第三方工具与代码之间的交互。这一章使用 C# 和 .NET GitHub API 库 Nancy 构建一个应用。

如果把按照特定方式组织的仓库推送到 GitHub 中,GitHub 会将其转换成功能完整的博客,基本上相当于 WordPress 网站(当然,没那么复杂)。第 6 章说明仓库的文件结构,如何在 Jekyll 网站中使用 Markdown,如何使用 Liquid 模板引擎提供的循环结构,以及如何使用 Ruby 语言开发一个工具,从 Internet Archive 中把整个网站导出到 Jekyll 网站中。这一章展示如何使用缓存爬取网站。使用 API 或第三方公开信息时缓存很有用。

第 7 章为 Android 操作系统开发一个移动应用。这个应用使用 GitHub API 的 Git Data 部分读取信息,再把信息写入一个 Jekyll 网站仓库。这一章展示如何使用 UI 测试工具 Calabash 为 Android 应用编写用户界面测试,验证 GitHub API 的响应。

Hubot 是一个 JavaScript(NodeJS)聊天机器人,技术人员使用它可以更进一步,由“DevOps”(开发运维)变成“ChatOps”(聊天运维)。第 8 章说明如何使用 GitHub API 的 Activity 和 Pull Requests 部分。此外,还说明如何模拟 GitHub 的通知,以及如何编写可测试的 Hubot 扩展(JavaScript 代码通常难以测试)。我们将把这些串在一起,构建一个机器人,让它自动分配拉取请求审查邀请。

你知道可以把整个“单页应用”托管在 GitHub 中吗?第 9 章说明如何使用 JavaScript 语言构建一个咖啡店信息应用,这个应用的数据库是普通的文件,托管在 GitHub 中。更重要的是,我们将展示如何编写可测试的 JavaScript 应用,说明如何模拟所需的 GitHub API。

本书不会介绍 Organizations API,因为这是 GitHub API 的一小部分,作用简单,只能列出组织,以及修改组织的元数据。学会 GitHub API 的其他部分后,这个不重要的部分自然就会用了。

本书也不会介绍 Users API。你可能觉得这一部分很重要,其实不然,Users API 只提供了一个端点,用于列出用户的信息、添加或删除 SSH 密钥、修改电子邮件地址和修改关注者。

本书没有为工单专开一章。以前,GitHub 把工单和拉取请求放在 API 的同一部分中,不过拉取请求越来越重要,所以 GitHub API 文档把它单独列为一部分。其实,在 GitHub 内部,二者仍然存储在同一个数据库中,而且拉取请求目前还是工单的一种。第 8 章将说明如何使用拉取请求,工单可以比照使用。

Enterprise API 几乎与 GitHub.com 网站的 API 一样,本书没有单写一章介绍企业版 API 的用法,不过在附录 B 中举了几个示例,说明如何使用企业版。本书还为各章使用的不同语言提供了企业版句法,这样书中的各个示例就能在企业版中使用了。

本书通过这些故事讲述如何使用 GitHub 背后的技术,希望借此让你一窥使用 GitHub API 构建应用的开发者是如何思考问题的。本书的目标读者

本书应该能为已经使用过 Git 或 GitHub 并想提升技能的读者提供有用的信息。没有用过 GitHub 或 Git 的读者应该先读一本入门

1书。

1. 可参考《GitHub 入门与实践》,人民邮电出版社出版。——编者注

你应该至少熟悉一门现代的命令式编程语言。本书不要求你是专家级程序员,但是要有一定的编程经验,至少熟悉一门编程语言。

你应该知道 HTTP 协议的基础知识。GitHub 团队设计 API 时采用了十分标准的 REST 式架构。你应该知道 GET 请求和 POST 请求的区别,至少要知道 HTTP 状态码的意思。

如果熟悉其他 Web API,阅读本书会轻松一些。本书的目标是告诉你如何使用架构、设计和测试良好的 API,构建有趣且强大的工具。如果你没怎么用过 Web API,但是用过其他类型的 API,这样也行。你将学到什么

本书主要介绍 GitHub 和强大的 GitHub API 提供的功能。不要以为这会限制你对 Git 的使用。假如你是 Android 开发者,使用 Git 管理应用的源码,如果你想在其他地方使用 Git,没问题,本书能打开你的视野,教你 Git 和 GitHub 的高级用法。如果你在自己的项目中已经使用 Git,想在更大的群体中推广 Git,本书会教你 GitHub 引领的“社交编程”风潮。本书为使用其他分布式版本控制系统的软件开发者架起了桥梁,能指引他们转用 Git 和 GitHub 这样的 Web 服务。

资深开发者都喜欢自动化工具。本书提供了一些示例,说明如何把单调的任务转换成可自动和重复执行的过程。这些示例使用多门编程语言编写,让你了解如何与 GitHub API 通信。

为了让本书适合更多的人群阅读,我们没有限定必须使用哪个编辑器或操作系统,很多示例程序都在命令行中执行。如果你不熟悉命令行,本书能让你深入了解它的用法,相信你读完本书之后会发现命令行的强大。如果从 5 岁起你的爸爸就强迫你使用命令行,导致你对它充满恨意,那么通过本书你将重新爱上 bash shell。

如果你能透过 GitHub 提供的技术看到其背后文化和思想的改变,很有可能会发现一种符合现代社会的工作方式。本书集中精力讨论工具本身,工具能做什么则由你自己去探索。

书中各章几乎都有对应的仓库,这些仓库托管在 GitHub 中,供你查看书中讨论的代码。

你可以随意派生这些示例,在自己的项目和工具中使用。

最后,本书会教你编写可测试的 API 后端代码。即便是最有经验的开发者,往往也觉得为代码编写测试是件有挑战的事,何况还要把测试代码写得像文学作品那样高深莫测。测试以 API 为后端的程序尤其艰难。我们要跳出单元测试的思维,以不同的方式思考。为了帮你跨过这道障碍,本书会告诉你怎么让与 GitHub API 交互的代码变得易于测试。GitHub钟爱的语言

有两门语言与 GitHub 密不可分,你要安装并使用它们才能更好地理解本书的内容。● Ruby这是一门简单、易读的编程语言,GitHub 公司的创始人在

公司早期广泛使用。● JavaScript这是唯一普遍使用的浏览器端编程语言,随着 NodeJS 的出

现,其重要性迈上了新的台阶,甚至与开发 Web 应用的服务器

端框架 Ruby on Rails 平起平坐了。独立开发者尤其喜爱该语

言。

不可否认,本书的很多读者都已经熟悉 Ruby 或 JavaScript/NodeJS 了,因此正文没有说明它们的基本用法和安装方式,而是放到了附录中。不过,附录也没有介绍这两门语言的句法,我们希望你有使用其他语言的经验,能读懂任何命令式语言编写的代码。书中各章讨论 GitHub API 的方方面面,偶尔会讲解语言细节,但是不管你熟悉哪门语言,书中的代码应该都通俗易懂。附录讨论了这两门语言在 GitHub 发展过程中的作用,还着重说明了一些特殊文件的作用和安装方式。

安装和使用这两门语言不会浪费你的时间,相反,能为你建立坚实的基础,以便深入探索 GitHub API。书中有几章使用 Ruby 或 JavaScript,所以花点时间学习基本句法有助于更好地理解书中的内容。对操作系统的要求

本书是两位作者在 MacBook Pro 中撰写的。MacBook 中都有 shell(“BASH”),与任何 Linux 设备中的 shell 几乎一样。如果你使用这两个操作系统,各章的代码都能顺利运行。

如果你使用 Windows 设备(或者没有 BASH shell 的操作系统),部分命令和代码示例可能无法运行,需要安装额外的软件才行。

简单的解决方法是使用 VirtualBox 和 Vagrant。VirtualBox 是免费的虚拟系统,能在 x86 硬件中使用。Vagrant 是开发环境管理工具。使用 VirtualBox 和 Vagrant 能快速安装 Linux 虚拟机。如果想安装这两个工具,分别访问 VirtualBox(https://www.virtualbox.org/wiki/Downloads)和 Vagrant(https://www.vagrantup.com/downloads.html)的下载页面。安装好之后,可以使用下述两个命令安装 Ubuntu 虚拟机:$ vagrant init hashicorp/precise32$ vagrant up不适合阅读本书的读者

本书探讨 GitHub API 的用法,没有限定于单一的语言,而是使用多门不同的语言。本书不仅说明了 GitHub 团队设计 API 的方式,还分析了不同编程语言和社区对客户端库的实现方式。我们相信这样能教你更多知识,因此,如果你只对某一门语言感兴趣,想知道如何使用那门语言与 GitHub API 交互,那么这本书就不适合你。

本书努力证明 API 驱动的代码可以测试,而且这么做是有好处的。但是本书不是测试编写手册,不会教你怎么写出最好的测试代码。我们使用多门语言,为的是不加入各个社区对测试框架的争论。我们认识到多数软件项目完全没有测试,因此本书的重点是帮你跨过这只大拦路虎。如果你从未写过测试,那么要转换一下思维方式。我们希望通过具体的示例让你(尤其是没有写过测试的读者)知道如何为使用 API 的代码编写测试。有些章节对应的仓库中有更详细的测试组件,书中的测试大都简略,没有涵盖全部边缘情况。使用代码示例

补充材料(代码示例、练习等)可以从 https://github.com/xrd/building-tools-with-github 下载。

本书是要帮你完成工作的。一般来说,如果本书提供了示例代码,你可以把它用在你的程序或文档中。除非你使用了很大一部分代码,否则无需联系我们获得许可。比如,用本书的几个代码片段写一个程序就无需获得许可,销售或分发 O'Reilly 图书的示例光盘则需要获得许可;引用本书中的示例代码回答问题无需获得许可,将书中大量的代码放到你的产品文档中则需要获得许可。

我们很希望但并不强制要求你在引用本书内容时加上引用说明。引用说明一般包括书名、作者、出版社和 ISBN。比如:“Building Tools with GitHub by Chris Dawson and Ben Straub (O'Reilly). Copyright 2016 Chris Dawson and Ben Straub, 978-1-491-93350-3.”

如果你觉得自己对示例代码的用法超出了上述许可的范围,欢迎你通过 permissions@oreilly.com 与我们联系。®Safari Books Online

Safari Books Online(http://www.safaribooksonline.com)是应运而生的数字图书馆。它同时以图书和视频的形式出版世界顶级技术和商务作家的专业作品。技术专家、软件开发人员、Web 设计师、商务人士和创意专家等,在开展调研、解决问题、学习和认证培训时,都将 Safari Books Online 视作获取资料的首选渠道。

对于组织团体、政府机构和个人,Safari Books Online 提供各种产品组合和灵活的定价策略。用户可通过一个功能完备的数据库检索系统访问 O'Reilly Media、Prentice Hall Professional、Addison-Wesley Professional、Microsoft Press、Sams、Que、Peachpit Press、Focal Press、Cisco Press、John Wiley & Sons、Syngress、Morgan Kaufmann、IBM Redbooks、Packt、Adobe Press、FT Press、Apress、Manning、New Riders、McGraw-Hill、Jones & Bartlett、Course Technology 以及其他几十家出版社的上千种图书、培训视频和正式出版之前的书稿。要了解 Safari Books Online 的更多信息,我们网上见。联系我们

请把对本书的评价和问题发给出版社。

美国:

  O'Reilly Media, Inc.

  1005 Gravenstein Highway North

  Sebastopol, CA 95472

中国:

  北京市西城区西直门南大街 2 号成铭大厦 C 座 807 室(100035)

奥莱利技术咨询(北京)有限公司

O'Reilly 的每一本书都有专属网页,你可以在那儿找到本书的相关信息,包括勘误表、示例代码以及其他信息。本书的网站地址是:

  http://shop.oreilly.com/product/0636920043027.do

对于本书的评论和技术性问题,请发送电子邮件到:bookquestions@oreilly.com

要了解更多 O'Reilly 图书、培训课程、会议和新闻的信息,请访问以下网站:

  http://www.oreilly.com

我们在 Facebook 的地址如下:http://facebook.com/oreilly

请关注我们的 Twitter 动态:http://twitter.com/oreillymedia

我们的 YouTube 视频地址如下:http://www.youtube.com/oreillymedia致谢

Chris 要感谢他可爱的妻子 Nicole。与我相处和持家的过程中你充满了智慧,真希望我能把这些智慧用到本书中。我的儿子 Roosevelt 活力四射,不断感染着我,即使我已筋疲力尽,也能给我前进的动力。感谢我的女儿 Charlotte,你像微笑的佛像那样让我安宁。感谢我的母亲,谢谢你教我写作,最重要的是,告诉我为什么写作,这是技术圈急需的技能。感谢 Tim O'Brien 邀请我参与这个项目,谢谢你,希望以后还有机会合作。感谢 Bradley

Horowitz,你证明了小小的善举可以产生极大的影响。还要感谢 David J. Groom,虽然我们从未谋面,但是你的建议和鼓舞对这本书极其重要,你的鼓励让我写完了这本书,如此才能与某一天阅读本书的读者结识。

Ben 要感谢他的妻子 Becky,谢谢她一直以来的支持,并在需要的时候督促他。没有她,世界将变得不完美。第1章开放的 GitHub API

本章开始介绍如何使用 GitHub API 读写数据。后续的章节说明如何使用不同的客户端库通过 GitHub API 访问信息。这些客户端库故意隐藏 API 的具体细节,为你提供简洁且符合习惯的方法,用于访问托管在 GitHub 中的 Git 仓库,查看和修改里面的数据。不过,本章直接分析 GitHub API,详细说明原始 HTTP 请求和响应。本章还会讨论访问 GitHub 中公开和隐私数据的不同方式,并指出各自的不足之处。此外,本章会概述网络受限时如何在 Web 浏览器中访问 GitHub 的数据。1.1 cURL

有时,你可能想立即通过 GitHub API 访问信息,而不想编写正式的程序;有时,你可能想立即获取 HTTP 原始请求的首部和内容;有时,你甚至可能会对客户端库的实现有疑惑,需要换个角度确认客户端库的行为是否正确。遇到这些情况时,最适合使用 cURL 这个简单的命令行 HTTP 工具。与最优秀的 Unix 工具一样,cURL 是个小型程序,功能十分专一,而且故意做了限制,只用于访问 HTTP 服务器。

cURL 与它熟谙的 HTTP 协议一样是无状态的。后面有一章会探讨这一局限性的解决方法,不过要注意,cURL 最适合用于发起一次性请求。 安装 cURL大多数 OS X 设备中通常都安装了 cURL,在 Linux 中可以使用包管理器轻易安装(执行 apt-get install curl 或 yum install curl 命令)。如果使用的是 Windows,或者想自己动手安装,请访问 http://curl.haxx.se/download.html。

下面来发起一个请求。我们从 GitHub API 最基本的端点入手,地址是 https://api.github.com。$ curl https://api.github.com{ "current_user_url": "https://api.github.com/user", "current_user_authorizations_html_url": "https://github.com/settings/connections/applications{/client_id}", "authorizations_url": "https://api.github.com/authorizations", "code_search_url": "https://api.github.com/search/code?q={query}{&page,per_page,sort,order}", "emails_url": "https://api.github.com/user/emails", "emojis_url": "https://api.github.com/emojis", ...}

为了便于阅读,此处省略了部分响应。有几点需要特别注意:响应中有大量指向附属信息的 URL,URL 中包含参数,此外响应的格式是 JSON。

我们从这个 API 的响应中能得知什么呢?1.2 列举API路径

GitHub API 是超媒体 API。超媒体的构成需要用一整本书才能说清楚(推荐阅读《使用 HTML5 和 Node 构建超媒体 API》),不过通过分析响应,我们能掌握超媒体的多数核心概念。首先,从前面那个 API 的响应可以看出,响应中包含一个映射,列出了接下来可能会发起请求的地址。当然,不是所有客户端都会使用这个信息,但是超媒体 API 的目标之一,是让客户端在不重新编写代码的前提下动态调整所用的端点。如果你觉得编写客户端时要考虑自动处理新端点,以防 GitHub 更改 API 这一点难以理解,不用太过担心,GitHub 非常负责,它像大多数公司那样,积极维护 API 并为其提供支持。不过要知道,API 中的 API 参考是值得信赖的,比外部文档可信,因为文档可能与 API 本身脱节。

API 中的映射富含数据。例如,映射不仅包含 URL,还有为 URL 提供参数的方式。在前面那个示例中,code_search_url 键对应的 URL 明显用于在 GitHub 中搜索代码,此外还指明了如何构建传给 URL 的参数。如果客户端够智能,能读懂这种纲领性的格式,就能动态生成查询,无需开发者去阅读 API 文档。至少,这是超媒体为我们指明的美好未来。如果你是怀疑论者,至少要知道 API(比如 GitHub)把文档嵌入自身当中,并且 GitHub 做了足够的测试,能够证明内嵌的文档与 API 端点传递的信息匹配。其他类型的 API 则没有这么强的保障。

下面,我们来简单讨论所有 GitHub API 的响应格式——JSON。1.3 JSON格式

GitHub API 返回的所有响应都是 JSON(JavaScript Object Notation,JavaScript 对象表示法)格式。JSON 是一种“轻量级数据交换格式”(详情参见 JSON.org 网站:http://www.json.org/)。此外,还有其他与之相争且有效的格式,例如 XML(Extensible Markup Language,可扩展标记语言)和 YAML(YAML Ain't Markup Language),不过 JSON 正在快速成为 Web 服务的事实标准。

JSON 之所以如此流行,有以下两个原因。● JSON 易于阅读。与 XML 等序列化格式相比,JSON 很好

地平衡了人类可读性。● 只需小幅修改(和程序员的认知处理),JSON 就能在

JavaScript 中使用。在客户端和服务器端都能同样良好使用的数

据格式一定会胜出,JSON 就是如此。

GitHub 最初使用 Ruby on Rails 工具栈开发(部分代码现在仍在运行),你可能觉得这样的网站应该支持指定替代格式(如 XML),但是 GitHub 不再支持 XML 了。JSON 万岁!

如果你用过其他基于文本的交换格式,会发现 JSON 特别简单。注意,JSON 只支持使用双引号,不支持单引号,这一点对于刚接触 JSON 的人来说可能有点难以理解,出乎意料。

我们使用 cURL 这个命令行工具从 GitHub API 中获取数据。如果再有一个简单的命令行工具能处理 JSON 就好了。下面介绍一个这样的工具。1.3.1 在命令行中解析JSON

JSON 是一种文本格式,因此可以使用任何命令行文本处理工具处理 JSON 响应,例如令人敬仰的 AWK。有一个专门解析 JSON 的优秀工具能补足 cURL,值得一用,这便是 jq。通过管道(大多数 shell 使用“|”字符)把 JSON 内容传给 jq 后,可以使用过滤器轻易提取 JSON 片段。 安装 jqjq 可以从源码安装,使用包管理器安装(例如 brew 或 apt-get),下载页面(http://stedolan.github.io/jq/download/)还有适用于 OS X、Linux、Windows 和 Solaris 的二进制文件。

下面深入前面的示例,从访问 api.github.com 后收到的 API 映射中提取感兴趣的信息:$ curl https://api.github.com | jq '.current_user_url' % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed100 2004 100 2004 0 0 4496 0 --:--:-- --:--:-- --:--:-- 4493"https://api.github.com/user"

发生了什么? jq 工具解析 JSON,然后使用 .current_user_url 过滤器从 JSON 响应中获取内容。再次查看响应,你会发现响应是个关联数组,里面有多个键值对。jq 使用那个关联数组中的 current_user_url 作为键获取对应的值。

你还会发现 cURL 把传输时间信息打印出来了。cURL 把这些信息打印到标准错误。这是 shell 的一种约定,用于输出错误。jq 会正确忽略这个输出流(也就是说,JSON 格式的数据流不会被错误消息搅乱)。如果想禁止那些信息,让请求清晰明了,可以使用 -s 开关,在“静默”模式中运行 cURL。

jq 在 JSON 响应上应用过滤器的方式易于理解。下面通过一个复杂的请求(例如,获取某个用户的所有公开仓库)说明如何使用 jq 的模式参数。我们要获取一组更为复杂的信息,即用户的仓库列表,以此说明如何使用 jq 从响应中提取信息:$ curl -s https://api.github.com/users/xrd/repos[ { "id": 19551182, "name": "a-gollum-test", "full_name": "xrd/a-gollum-test", "owner": { "login": "xrd", "id": 17064, "avatar_url": "https://avatars.githubusercontent.com/u/17064?v=3", ... }]$ curl -s https://api.github.com/users/xrd/repos | jq '.[0].owner.id'17064

这个响应的结构与之前不同,它不是一个关联数组,而是一个普通数组(有多个元素)。为了获取第一个元素,我们要指定数字索引,然后再通过键进入元素里的关联数组,从而获取所需的内容——属主的 ID。

jq 工具能很好地检查 JSON 的有效性。前面说过,JSON 的键值对只能使用双引号,不能使用单引号。可以使用 jq 验证 JSON 是否有效,以及是否满足这个要求:$ echo '{ "a" : "b" }' | jq '.'{ "a": "b"}$ echo "{ 'no' : 'bueno' }" | jq "."parse error: Invalid numeric literal at line 1, column 7

传给 jq 的第一个 JSON 是有效的,而第二个 JSON 使用了无效的单引号字符,因此报错了。jq 过滤器是以字符串形式传递的参数,而把字符串提供给 jq 的 shell 不管你使用的是单引号还是双引号,从上述代码可以看出这一点。如果你不知道 echo 命令的作用,我告诉你,它会把传给它的任何字符串打印出来。把这个命令和管道符号结合起来,可以通过标准输入轻易地把字符串提供给 jq。

jq 是个强大的工具,能从任何 JSON 响应中迅速获取内容。此外,jq 还有很多强大的功能,详情参见文档(https://stedolan.github.io/jq/)。

至此,我们知道如何仅使用一行命令完成从 GitHub API 中获取所需的信息,并从响应中解析出信息片段。可是,有时为 cURL 或 API 指定的参数可能是错误的,获得的数据不是我们想要的。接下来,我们学习如何调试 cURL 工具和 API 服务本身,从而在出错时获取更多的信息。1.3.2 cURL的调试开关

前面说过,cURL 是验证响应是否与预期相符的绝佳工具。响应主体很重要,但是通常还要获取首部。为 cURL 指定 -i 和 -v 开关能轻易获取这些信息。-i 开关打印请求首部,-v 开关则打印请求和响应首部(> 符号表示请求数据,< 符号表示响应数据)。$ curl -i https://api.github.comHTTP/1.1 200 OKServer: GitHub.comDate: Wed, 03 Jun 2015 19:39:03 GMTContent-Type: application/json; charset=utf-8Content-Length: 2004Status: 200 OKX-RateLimit-Limit: 60...{ "current_user_url": "https://api.github.com/user", ...}$ curl -v https://api.github.com Rebuilt URL to: https://api.github.com/ Hostname was NOT found in DNS cache Trying 192.30.252.137... Connected to api.github.com (192.30.252.137) port 443 (#0) successfully set certificate verify locations: CAfile: none CApath: etcssl/certs SSLv3, TLS handshake, Client hello (1): SSLv3, TLS handshake, Server hello (2):... CN=DigiCert SHA2 High Assurance Server CA SSL certificate verify ok.> GET HTTP1.1> User-Agent: curl/7.35.0> Host: api.github.com> Accept: />< HTTP/1.1 200 OK* Server GitHub.com is not blacklisted...

指定 -v 开关能获取所有信息:DNS 查询、SSL 证书链中的信息,以及完整的请求和响应信息。 注意,如果打印首部,jq 这样的工具会迷惑不解,因为提供的不是纯粹的 JSON。

本节旨在说明不仅主体(JSON 数据)中有值得关注的信息,首部中也有。我们要知道有哪些首部,还要知道哪些是重要的。根据 HTTP 规范,需要的首部有很多,这些首部通常可以忽略,不过如果请求不是相互独立的,有些首部则是必不可少的。1.4 重要的首部

GitHub API 的每个响应中都有三个用于指明 API 频率限制的首部,分别是 X-RateLimit-Limit、X-RateLimit-Remaining 和 X-RateLimit-Reset。这些限制在 1.7.6 节详述。

从 GitHub API 中获取文本或 blob 内容时,要用到 X-GitHub-Media-Type 首部中包含的信息。向 GitHub API 发起请求时,可以在请求中发送 Accept 首部,指明想使用的格式。

下面,我们使用一个响应构建另一个响应。1.5 跟随超媒体API

我们要使用 API 基端点返回的“映射”,手动生成另一个请求:$ curl -i https://api.github.com/HTTP/1.1 200 OKServer: GitHub.comDate: Sat, 25 Apr 2015 05:36:16 GMT...{ "current_user_url": "https://api.github.com/user", ... "organization_url": "https://api.github.com/orgs/{org}", ...}

我们可以使用组织的 URL,把占位符替换成 "github":$ curl https://api.github.com/orgs/github{ "login": "github", "id": 9919, "url": "https://api.github.com/orgs/github", ... "description": "GitHub, the company.", "name": "GitHub", "company": null, "blog": "https://github.com/about", "location": "San Francisco, CA", "email": "support@github.com", ... "created_at": "2008-05-11T04:37:31Z", "updated_at": "2015-04-25T05:17:01Z", "type": "Organization"}

通过上述信息可以得知 GitHub 的一些信息。我们得知 GitHub 的博客地址是 https://github.com/about,公司位于旧金山,组织的创建日期是 2008 年 5 月 11 日。从博客中一篇发布于 4 月份的文章(https://github.com/blog/40-we-launched)中得知,GitHub 公司在这一个月之前就成立了。或许公司成立一个月之后才在 GitHub 网站中添加组织功能吧。

目前,我们发起的请求都用于获取公开信息。GitHub API 提供的信息十分丰富,但是验证身份之后才能访问隐私信息和不可公开使用的服务。例如,想使用 API 向 GitHub 中写入数据的话,需要知道如何验证身份。1.6 身份验证

向 GitHub API 发起请求时,有两种身份验证方式:用户名和密码(HTTP 基本验证)以及 OAuth 令牌。1.6.1 用户名和密码验证

提供用户名和密码后可以访问 GitHub 中受保护的内容。用户名验证使用 HTTP 基本验证实现,在 cURL 中使用 -u 标志指定。HTTP 基本验证就是用户名和密码验证:$ curl -u xrd https://api.github.com/rate_limitEnter host password for user 'xrd': xxxxxxxx{ "rate": { "limit": 5000, "remaining": 4995, "reset": 1376251941 }}

上述 cURL 命令先通过 GitHub API 的身份验证,然后获取该用户账号具体的频率限制信息。这些是受保护的信息,只有登录的用户才能查看。

1. 用户名验证的优点

几乎所有客户端库都支持 HTTP 基本验证。我们即将介绍的 GitHub API 客户端都支持用户名和密码验证。而且,自己实现客户端也很容易,因为这是 HTTP 标准的核心功能。所以,开发客户端时只要使用了符合标准的 HTTP 库,就能访问 GitHub API 中的内容。

2. 用户名验证的缺点

使用用户名和密码验证管理 GitHub API 的访问权限不合适,原因有如下几个。● HTTP 基本验证是旧协议,没有预料到 Web 服务的粒度如

此细化。如果通过用户名和密码验证用户的身份,那么无法指定

让 Web 服务开放哪些特定的功能。● 如果使用用户名和密码在手机端访问 GitHub API 的内容,

又在笔记本电脑中访问 API 的内容,那就无法禁止某一台设备

访问,只能都禁止。● HTTP 基本验证无法扩展验证流程。现今,很多现代服务都

支持双重身份验证,为了把这种验证方式插入现有的验证过程,

需要修改 HTTP 客户端(例如 Web 浏览器),至少也要修改客

户端预期的流程(让浏览器重复请求)。

这些问题在 OAuth 流程中都能得到解决(或者至少得到支持)。鉴于这些缺点,仅当便利性至上时才应当使用用户名和密码验证身份。1.6.2 OAuth

OAuth 是一种身份验证机制,把令牌与功能或客户端绑定起来。也就是说,可以指定让服务为 OAuth 令牌开放哪些功能;还可以颁发多个令牌,与不同的客户端绑定,例如手机应用、笔记本电脑、智能手表,甚至是接入物联网的烤箱。更重要的是,可以吊销令牌而不对其他令牌产生影响。

OAuth 令牌主要的缺点是增加了一层复杂度,如果你只用过 HTTP 基本验证,对此可能不熟悉。HTTP 基本验证通常只需在 HTTP 请求中添加一个额外的首部,或者在客户端工具(如 cURL)中添加一个额外的标志。

OAuth 能解决上述问题,方法是把令牌限定在作用域(指定 Web 服务的功能子集)中,以及按需为不同的客户端生成不同的令牌。

1. 作用域:指定验证令牌可执行的操作

生成 OAuth 令牌时,要指定所需的访问权限。下述示例虽然使用 HTTP 基本验证创建令牌,但是一旦得到令牌,后续请求就不再需要使用 HTTP 基本验证。获颁 OAuth 令牌之后,便有权限读写相应用户的公开仓库。

下述 cURL 命令使用 HTTP 基本验证请求令牌:$ curl -u username -d '{"scopes":["public_repo"]}' \https://api.github.com/authorizations{ "id": 1234567, "url": "https://api.github.com/authorizations/1234567", "app": { "name": "My app", "url": "https://developer.github.com/v3/oauth_authorizations/", "client_id": "00000000000000000000" }, "token": "abcdef87654321 ...}

请求成功后获得的 JSON 响应中有个令牌,把它提取出来之后可以提供给应用,用于访问 GitHub API。

如果使用双重身份验证,这个过程需要额外的步骤,详情参阅第 8 章。

令牌的使用方法是,在 Authorization 首部中指定令牌:$ curl -H "Authorization: token abcdef87654321" ...

作用域明确了服务或应用能如何使用 GitHub API 中的数据。对于供用户自己使用的令牌来说,作用域便于稽查用户如何使用 API 提供的信息。不过,当第三方应用想访问你的信息时,最能体现作用域明确访问权限的重要价值和防护作用,因为你能确保应用只能访问允许它访问的数据,而且便于取消访问权限。

2. 作用域的不足

要知道,作用域有个极大的不足之处:无法精细调整特定仓库的访问权限。如果允许访问任何一个私有仓库,那么所有仓库就都能访问。

未来,GitHub 可能会修改作用域的工作方式,解决其中一些问题。OAuth 机制的好处是,发生变化后,只需请求重新设定作用域的令牌,应用的身份验证流程则无需修改。 构建服务或应用时,要特别谨慎地对待请求的作用域。用户会担忧交给你的数据是否安全(这是正常的),他们会根据请求的作用域评估能否信任应用。如果用户觉得不需要那么广的作用域,请求授权时一定要从提供给 GitHub 的权限列表中删除,与用户建立一定的信任之后再考虑升级为更广的作用域。

3. 逐步升级作用域

你可以先请求严格受限的作用域,以后再请求更广的作用域。例如,用户首次访问你的应用时,你可以只获取 user 作用域,在你的服务中创建用户对象,仅当应用需要获取用户的仓库信息时再请求升级权限。此时,用户需要接受或拒绝升级请求。但是,事无巨细,(在与用户建立关系之前)什么都询问,往往会导致用户放弃登录。

下面详述使用 OAuth 验证身份的细节。

4. 简化的OAuth流程

OAuth 有很多版本,GitHub 使用的是 OAuth2。OAuth2 验证身份的流程如下:

(1) 应用请求访问;

(2) 服务提供方(GitHub)请求验证身份,通常使用用户名和密码;

(3) 如果启用了双重身份验证,询问 OTP(one-time password,一次性密码);

(4) GitHub 返回包含令牌的 JSON 响应;

(5) 应用使用 OAuth 令牌请求 API。

接下来说明 GitHub API 在通信过程中用于提供反馈的各个 HTTP 状态码。1.7 状态码

GitHub API 使用 HTTP 状态码明确表明请求的处理结果。如果使用的是简单的客户端,如 cURL,在获取数据之前一定要先验证状态码。如果自己编写 API 客户端,首先要重点关注状态码。刚开始使用 GitHub API 的用户应该仔细检查响应的状态码,熟悉请求可能致错的各种状况。1.7.1 成功(200或201)

只要你用过 HTTP 客户端,就知道 HTTP 状态码“200”表示成功。请求的目标地址和相关的参数正确时,GitHub 响应的状态码是 200。如果请求在服务器中创建内容,响应的状态码是 201,表示成功在服务器中创建了内容。$ curl -s -i https://api.github.com | grep StatusStatus: 200 OK1.7.2 不合规的JSON(400)

如果载荷(请求中发送的 JSON)无效,GitHub API 的响应是 400 错误,如下所示:$ curl -i -u xrd -d 'yaml: true' -X POST https://api.github.com/gistsEnter host password for user 'xrd':HTTP/1.1 400 Bad RequestServer: GitHub.comDate: Thu, 04 Jun 2015 20:33:49 GMTContent-Type: application/json; charset=utf-8Content-Length: 148Status: 400 Bad Request...{ "message": "Problems parsing JSON", "documentation_url": "https://developer.github.com/v3/oauth_authorizations/#create...authorization"}

这里,我们打算使用 Gist API 文档(https://developer.github.com/v3/gists/#create-a-gist)中给出的端点新建一个 Gist。后面有一章会详细讨论 Gist。这个请求失败了,因为我们使用的不是 JSON(看起来使用的像是 YAML,参见第 6 章)。载荷使用 -d 开关发送。GitHub 在返回的 JSON 响应中使用 documentation_url 键提供了一个地址,告诉你在哪里寻找正确格式的文档。注意,我们使用了 -X 开关并把值设为 POST,这么做是为了告诉 cURL 向 GitHub 发起 POST 请求。1.7.3 错误的JSON(422)

如果请求中有任何无效的字段,GitHub 会响应 422 错误。下面我们尝试修复前面那个请求。根据文档,JSON 载荷应该使用下述格式:{ "description": "the description for this gist", "public": true, "files": { "file1.txt": { "content": "String file contents" } }}

如果 JSON 是有效的,但是字段不正确呢?$ curl -i -u chris@burningon.com -d '{ "a" : "b" }' -X POSThttps://api.github.com/gistsEnter host password for user 'chris@burningon.com':HTTP/1.1 422 Unprocessable Entity...{ "message": "Invalid request.\n\n\"files\" wasn't supplied.", "documentation_url": "https://developer.github.com/v3"}

注意两件事。其一,返回的是 422 错误,表示 JSON 有效,但是字段不正确。其二,获得一个说明错误原因的响应:请求载荷中缺

试读结束[说明:试读内容隐藏了图片]

下载完整电子书


相关推荐

最新文章


© 2020 txtepub下载