Month: 九月 2017

[The Egg](http://www.galactanet.com/oneoff/theegg_zh.html)

Written by Andy Weir

Translation: Xiuzhu Shao

“`

你在回家的路上死了。
那是一场车祸。不大,但仍然致命。你留下了妻子和两个孩子。你死的并不痛苦。救护员尽力去救你,但没有成功。你的身体被摔得太彻底了。死了很好,相信我。
这时你遇见了我。
“发生了什么?”你问,“我在那儿?”
“你死了。”我说,没有必要拐弯抹角。
“有一辆。。。一辆卡车失控。。。”
“对。”我说。
“我。。。我死了?”
“对。但别难过,每个人都会死。”我说。
你看了看周围,一片虚空,只有你和我。“这是什么地方?”你问,“是来世吗?”
“差不多吧。”我说。
“你是上帝?”你问。
“对,”我回答,“我是上帝。”
“我的孩子。。。我的老婆。。。”你说。
“怎么了?”
“他们会好吗?”
“这正是我想看到的,”我说,“你刚刚去世,但主要关心的是你的家人。这是好事。”
你充满好奇地看着我。在你眼里,我并不像神。我只像一个普通的男人,或许一个女人,一种模糊的权威形象。比起上帝,我长得更像一位老师。
“别担心,”我说,“他们会好起来的。你的孩子们会把你记得十全十美。他们还来不及发展对你得敌意。你的妻子表面上会哭,但其实会暗暗松一口气。说实在的,你们的婚姻已经破裂了。如果这是任何安慰的话,她会为此感到非常内疚。”
“哦,”你说,“那现在会发生什么?我会去天堂还是地狱还是到哪里?”
“都不会,”我说,“你会重新投胎。”
“啊,”你说,“原来印度教是对的。”
“每一个宗教都有他们自己对的地方,”我说,“和我一起走吧。”
你跟着我大步穿行于虚空。“我们去哪儿呢?”
“不是什么特别的地方,”我说。“刚好我们可以边走边谈。”
“那最终的目的是什么呢?”你问,“我重生的时候,会变成一张白纸,对吗?一个婴儿。所以我此生所有的经历和所做的一切都不再有意义。”
“不是这样!”我说,“你之中包含有你累生累世所有的知识和经验。只是现在你不记得它们了。”
我停下脚步,握住你的肩膀。“你的灵魂比你所能想象的任何东西都更为壮观、美丽和巨大,人类的头脑只可容纳你的一小部分。就像你把手指放进一杯水里试探温度一样,你只把自己小小的一部分放进身体这个容器。但当你把它拿回时,你就获得了这个容器的所有经验。”
“你才在一个人体里过了48年,所以你还没有充分伸展你自己,觉悟到你其余的庞大意识。如果我们在这里逗留足够长的时间,你会开始记起一切。但一生和一生之间没有必要这样做。”
“那我曾转过多少次世呢?”
“哦,很多,很多很多。很多不同的生命。”我说,“接下来,你是一个活在公元540年的中国农家姑娘。”
“等等,什么?”你结结巴巴地说,“你要把我送回过去?”
“理论上说,我想是这样吧。你所知道的时间其实只存在于你的世界里。而在我的世界里,一切都不同。”
“你从哪里来?”你问。
“哦,”我解释道,“我来自某一个地方,另一个地方。那儿有很多和我一样的存在。我知道你想知道那儿是什么样子,但老实说,你不会理解。”
“哦,”你说,有点失望。“但等等。如果我恰巧转世到一个地方,我很可能曾经与我自己在某一点相遇。”
“当然,这种情况经常发生。但每一个生命只晓得它自己的周期,所以你根本不知道它实际在发生。”
“那这一切的意义是什么呢?”
“真的吗?”我问,“当真?你在问我生命的意义?不觉的有点老套?”
“但这的确是一个合理的问题。”你坚持。
我看着你的眼睛。“生命的意义,也是我创造整个宇宙的原因,是为了让你成熟。”
“你是指人类?你想让我们成熟?”
“不,只有你。我为你创造了整个宇宙。你每一次的生命都让你成长和成熟,成为一个更大的、更伟大的智者。”
“只是我吗?其他人怎么办?”
“没有别人,”我说,“这个宇宙里只有你和我。”
你茫然地盯着我,“但地球上所有的人。。。”
“全是你,不同化身的你。”
“等等,我是每个人?!”
“你终于懂了,”我说,祝贺地拍了拍你的背。
“我是每一个活过的人?”
“还是未来每一个将要活的人,对。”
“我是林肯?”
“你也是约翰·布斯。”我说。
“我是希特勒?”你震惊地说。
“你也是被他杀死的几百万人。”
“我是耶稣?”
“你也是跟随他的每一个人。”
你沉默了。
“你每次害了一个人,”我说,“你就在害自己。你每一次善意的行动,都是对自己的善意。任何人所经历的每一个快乐和悲伤的时刻,都曾经被你,或将会被你,所经历。”
你想了很久。
“为什么?”你问我,“为什么你要做这一切?”
“因为有一天,你会变得和我一样。因为这就是你的本来面目,你和我是同类,你是我的孩子。”
“哇,”你难以置信地说,“你的意思是说我是上帝?”
“不,还不是。你还是个胎儿,你还在发育。一旦你活过所有时间的所有人的生命之后,你才会发育到足够成熟去获得新生。”
“那整个宇宙,”你说,“只是一个。。。”
“蛋。”我回答,“现在时间到了,该让你进入下一个生命了。”
然后我把你送上了路。
“`

The Egg

Written by Andy Weir

Translation: Xiuzhu Shao

蛋

你在回家的路上死了。
那是一场车祸。不大,但仍然致命。你留下了妻子和两个孩子。你死的并不痛苦。救护员尽力去救你,但没有成功。你的身体被摔得太彻底了。死了很好,相信我。
这时你遇见了我。
“发生了什么?”你问,“我在那儿?”
“你死了。”我说,没有必要拐弯抹角。
“有一辆。。。一辆卡车失控。。。”
“对。”我说。
“我。。。我死了?”
“对。但别难过,每个人都会死。”我说。
你看了看周围,一片虚空,只有你和我。“这是什么地方?”你问,“是来世吗?”
“差不多吧。”我说。
“你是上帝?”你问。
“对,”我回答,“我是上帝。”
“我的孩子。。。我的老婆。。。”你说。
“怎么了?”
“他们会好吗?”
“这正是我想看到的,”我说,“你刚刚去世,但主要关心的是你的家人。这是好事。”
你充满好奇地看着我。在你眼里,我并不像神。我只像一个普通的男人,或许一个女人,一种模糊的权威形象。比起上帝,我长得更像一位老师。
“别担心,”我说,“他们会好起来的。你的孩子们会把你记得十全十美。他们还来不及发展对你得敌意。你的妻子表面上会哭,但其实会暗暗松一口气。说实在的,你们的婚姻已经破裂了。如果这是任何安慰的话,她会为此感到非常内疚。”
“哦,”你说,“那现在会发生什么?我会去天堂还是地狱还是到哪里?”
“都不会,”我说,“你会重新投胎。”
“啊,”你说,“原来印度教是对的。”
“每一个宗教都有他们自己对的地方,”我说,“和我一起走吧。”
你跟着我大步穿行于虚空。“我们去哪儿呢?”
“不是什么特别的地方,”我说。“刚好我们可以边走边谈。”
“那最终的目的是什么呢?”你问,“我重生的时候,会变成一张白纸,对吗?一个婴儿。所以我此生所有的经历和所做的一切都不再有意义。”
“不是这样!”我说,“你之中包含有你累生累世所有的知识和经验。只是现在你不记得它们了。”
我停下脚步,握住你的肩膀。“你的灵魂比你所能想象的任何东西都更为壮观、美丽和巨大,人类的头脑只可容纳你的一小部分。就像你把手指放进一杯水里试探温度一样,你只把自己小小的一部分放进身体这个容器。但当你把它拿回时,你就获得了这个容器的所有经验。”
“你才在一个人体里过了48年,所以你还没有充分伸展你自己,觉悟到你其余的庞大意识。如果我们在这里逗留足够长的时间,你会开始记起一切。但一生和一生之间没有必要这样做。”
“那我曾转过多少次世呢?”
“哦,很多,很多很多。很多不同的生命。”我说,“接下来,你是一个活在公元540年的中国农家姑娘。”
“等等,什么?”你结结巴巴地说,“你要把我送回过去?”
“理论上说,我想是这样吧。你所知道的时间其实只存在于你的世界里。而在我的世界里,一切都不同。”
“你从哪里来?”你问。
“哦,”我解释道,“我来自某一个地方,另一个地方。那儿有很多和我一样的存在。我知道你想知道那儿是什么样子,但老实说,你不会理解。”
“哦,”你说,有点失望。“但等等。如果我恰巧转世到一个地方,我很可能曾经与我自己在某一点相遇。”
“当然,这种情况经常发生。但每一个生命只晓得它自己的周期,所以你根本不知道它实际在发生。”
“那这一切的意义是什么呢?”
“真的吗?”我问,“当真?你在问我生命的意义?不觉的有点老套?”
“但这的确是一个合理的问题。”你坚持。
我看着你的眼睛。“生命的意义,也是我创造整个宇宙的原因,是为了让你成熟。”
“你是指人类?你想让我们成熟?”
“不,只有你。我为你创造了整个宇宙。你每一次的生命都让你成长和成熟,成为一个更大的、更伟大的智者。”
“只是我吗?其他人怎么办?”
“没有别人,”我说,“这个宇宙里只有你和我。”
你茫然地盯着我,“但地球上所有的人。。。”
“全是你,不同化身的你。”
“等等,我是每个人?!”
“你终于懂了,”我说,祝贺地拍了拍你的背。
“我是每一个活过的人?”
“还是未来每一个将要活的人,对。”
“我是林肯?”
“你也是约翰·布斯。”我说。
“我是希特勒?”你震惊地说。
“你也是被他杀死的几百万人。”
“我是耶稣?”
“你也是跟随他的每一个人。”
你沉默了。
“你每次害了一个人,”我说,“你就在害自己。你每一次善意的行动,都是对自己的善意。任何人所经历的每一个快乐和悲伤的时刻,都曾经被你,或将会被你,所经历。”
你想了很久。
“为什么?”你问我,“为什么你要做这一切?”
“因为有一天,你会变得和我一样。因为这就是你的本来面目,你和我是同类,你是我的孩子。”
“哇,”你难以置信地说,“你的意思是说我是上帝?”
“不,还不是。你还是个胎儿,你还在发育。一旦你活过所有时间的所有人的生命之后,你才会发育到足够成熟去获得新生。”
“那整个宇宙,”你说,“只是一个。。。”
“蛋。”我回答,“现在时间到了,该让你进入下一个生命了。”
然后我把你送上了路。

前端框架 Vue 学习笔记

之前在网页里小范围的用了vue, 感觉用起来非常爽, 现在打算做自己的笔记应用. 这次打算做成SPA的形式, 前端全部用vue来写. 需要node的一些东西, 记录下学习过程. 迈向全栈,哈哈 ^_^

安装

首先, 全局安装vue:

npm install --global @vue/cli

data 属性

只有在创建时提供的 data 属性才是响应式的,在创建之后在添加新元素就不管用了。

当然还可以使用 app.$watch 方法显式创建一些监听器

// $watch 是一个实例方法
vm.$watch('a', function (newValue, oldValue) {
  // 这个回调将在 `vm.a` 改变后调用
})

methods 和 computed

methods 定义了一些可以调用的方法,他的值也可以用来插值。但是最好使用 computed,因为 computed 是有缓存的。

computed 属性也可以设置 setter,所以实际上,computed 属性相当于对现有属性的一种映射和变化。

v-bind 和 v-model

  • v-bind 用于单项绑定:在 HTML 属性中使用 v-bind 绑定, 标签中使用 { }。只能使用表达式,而不能使用语句。
  • v-model 用于双向绑定:在 input 这类用户可以输入的组件中,需要双向绑定,使用 v-model.

v-bind 类似的指令还有 v-once 和 v-html

v-model 实际上等价于

<input v-model="searchText">
<input
  v-bind:value="searchText"
  v-on:input="searchText = $event.target.value"
>

要想在自定义输入组件中支持 v-model 的话,就需要使用 v-bind 和 v-on 两个方法了,而不能直接使用 v-model。

v-if 和 v-for

这两个就和所有模板系统中的 if 和 for 一样。vue 中提供的额外方便之处是,可以使用 template 标签,这样就不会多一个标签了

vue 是懒渲染的,因此会尽可能地复用组件,可以使用 key 来区分

v-if 是真正的条件式渲染,v-show 则只是在切换 display 属性

vue 没有代理数组的赋值方法,所以需要使用 app.$set 方法

@

如果只是指定一个事件处理函数的话,那么参数就是 event。如果自己指定了参数的话,可以使用 $event 来代表 event

还可以使用 .prevent 和 .stop 等修饰符

component

vue 中最终要的概念就是组件了。使用组件来模块式得构建应用。需要通过 props 属性来定义组件中的属性

<div id="app-7">
  <ol>
    <!--
      现在我们为每个 todo-item 提供 todo 对象
      todo 对象是变量,即其内容可以是动态的。
      我们也需要为每个组件提供一个“key”,稍后再
      作详细解释。
    -->
    <todo-item
      v-for="item in groceryList"
      v-bind:todo="item"
      v-bind:key="item.id">
    </todo-item>
  </ol>
</div>

Vue.component('todo-item', {
  // todo-item 组件现在接受一个
  // "prop",类似于一个自定义特性。
  // 这个 prop 名为 todo。
  props: ['todo'],
  template: '<li>{{ todo.text }}</li>'
})

props 是一个数组,用来声明组建的属性。然后通过属性来传递。

组件还可以通过 $emit 来发送事件,这些事件可以被所有的组件监听到,就像普通的 DOM 事件一样。

声明周期函数

在固定的周期,vue 会调用的一些函数 created, mounted 等。需要注意的是,不要使用胖箭头函数。

new Vue({
  data: {
    a: 1
  },
  created: function () {
    // `this` 指向 vm 实例
    console.log('a is: ' + this.a)
  }
})
// => "a is: 1"

创建vue应用

因为我们会直接通过*.vue文件来编写vue的组件, 因此需要使用webpack打包编译. 另外我们需要使用官方的vue-router来

vue init webpack notelet

这条命令基于 webpack 这个模板创建了notelet这个应用, 也就是我们的笔记应用.

打开 src/router/index.js 可以看到 vue 创建的router的代码, 其中@src目录的缩写.

import Vue from 'vue'
  import Router from 'vue-router'
import Hello from '@/components/Hello'

Vue.use(Router)

export default new Router({
  routes: [
    {
    ¦ path: '/',
    ¦ name: 'Hello',
    ¦ component: Hello
    }
  ]
})

然后打开 src/main.js, 可以看到在里面使用了 App 来作为我们的跟组件

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  template: '<App/>',
  components: { App }
})

执行 npm run dev, 然后打开 http://localhost:8080/ 就可以看到我们的vue应用了. 注意, 在写这篇文章的时候 node 8.x 下似乎有bug, 导致 app.js 加载不出来, 安装 6.x 就好了. 该死的node.

打开 App.vue, 也就是我们的根组件, 可以看到下面的内容

<template>
  <div id="app">
  ¦ <router-view></router-view>
  </div>
</template>

<script>
export default {
  name: 'app'
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

注意其中的 router-view 便签, 意思就是路由的内容都在 router-view 中显示.

添加一个新的组件和路由

接下来我们添加一个"关于"页面. 打开src/router/index.js, 改成下面这样:

export default new Router({
  routes: [
  ¦ {
  ¦ ¦ path: '/',
  ¦ ¦ name: 'Hello',
  ¦ ¦ component: Hello
  ¦ },
  ¦ {
  ¦ ¦ path: '/about',
  ¦ ¦ name: 'About',
  ¦ ¦ component: About
  ¦ }
  ]
})

然后添加 src/components/About.vue 文件

<template>
  <div class="hello">
  ¦ <h1>About Notelet</h1>
  ¦ <p>This is a simple note app</p>
  </div>
</template>

<script>
export default {
  name: 'About',
  data () {
  ¦ return {
  ¦ ¦ msg: 'Hello Vue'
  ¦ }
  }
}
</script>

然后更改 App.vue 文件

<template>
  <div id="app">
  ¦ <router-link :to="{name: 'Hello'}">Home</router-link>
  ¦ <router-link to="/about">About</router-link>
  ¦ <router-view></router-view>
  </div>
</template>

注意, 我们使用about指向了 About 这个组件, 而使用 hello 指向了 Hello 这个组件, 注意其中还动态传递了参数.

[1] https://scotch.io/tutorials/getting-started-with-vue-router

HTTP 认证介绍

周末给一个库添加http代理的支持,发现对http basic auth不甚了解,阅读了一下相关的文档,写篇备忘。

http 中的认证主要是 basic auth 和 digest auth 两种,其中 digest auth 比较复杂,而且也没有提升安全性,已经不建议使用了。

RFC 7235 [1] 描述了客户端(通常是浏览器)和服务器如何通过http进行身份认证的一些机制。客户端和 http代理之间也可以使用 http auth 来做验证。
 
# 验证流程

1. 当客户端访问一个页面时,如果只有验证后才能访问,或者验证后有更多内容,服务器应该发送 401 Unauthorized,提出一个chanllenge,设定 `WWW-Authenticate` header,并指定验证的 type 和 realm,具体定义下文有讲。
2. 客户端这时通常应该提示用户输入密钥,一般是浏览器弹出用户名密码对话框供用户填写,然后使用`Authorization` header发送验证的密钥。如果验证通过的话,应该正常访问(200 OK),验证通过但是没有权限的话应该返回 403 Forbidden。
3. 如果验证不通过,应该服务器返回401,客户端可以重试。

注意,如果客户端已经知道需要密钥访问,那么可以在第一个请求直接发送对应的密钥,这样就避免了 401 Unauthorized。

![MDN上的流程图](https://mdn.mozillademos.org/files/14689/HTTPAuth.png)
 

# 代理验证的不同

如果代理服务器需要验证的话,流程是类似的,有两点细节不同:

1. 代理服务器应该发送407 Proxy Authentication Required 而不是 401。使用的headers也变成了 Proxy-Authenticate 和 Proxy-Authorization 。
2. 服务器的头部 WWW-Authenticate 是 end-to-end 的,也就是代理服务器不应该篡改,应该原样传递。而代理服务器的Proxy-头部是 hop-by-hop 的,也就是不能向下传递。

# 实现细节

服务器或者代理服务器随着4XX发送的头部为

“`
WWW-Authenticate: realm=
or
Proxy-Authenticate: realm=
“`

其中 type 指定了使用的验证的类型,也就是用户名和密码加密方式的不同,IANA钦定了一批方法[2]。然鹅,一般来说常用的只有两个 Basic 和 Digest。而其中 Digest 的实现可能会要求服务器明文存储密码,于是大家又angry了[3],这里也不推荐使用。所以这里只介绍 Basic类型。

realm 指定了验证的领域,也就是说相同realm下的用户名和密码是一样的,如果你访问的两个页面在同一个realm,那么浏览器在第二次访问就不会问你密码了。

客户端发送对应的头部和密钥来获得访问权限

“`
Authorization:
or
Proxy-Authorization:
“`

其中,type就是刚刚的那个 Basic 或者 Digest。credentials 按照对应的方法计算。对于Basic类型 `credentials = base64(username + ‘:’ + password)`

一个例子,假设用户名和密码分别是:aladdin和opensesame。那么客户端应该发送的header是:`Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l`

# 需要注意的地方

1. 因为http协议本身是无状态的,所以Auth应该是无状态的,所以每次请求都应该携带。
 
2. 如果是http协议的话,对于Basic Auth,那么密码都是明文发送的,可以使用https来避免这个问题。

3. 可以使用:https://username:password@www.example.com/ 这种形式来预先输入账号密码,但是这种形式已经不鼓励了。不过在设定一些环境变量时,比如 http_proxy,也只能用这种方法来制定用户名和密码

参考:

1. 对应的RFC https://tools.ietf.org/html/rfc7235
2. IANA 注册的auth类型 http://www.iana.org/assignments/http-authschemes/http-authschemes.xhtml
3. 为什么不要使用digest验证  https://stackoverflow.com/questions/2384230/what-is-digest-authentication
4. MDN的文章还提供了如何让apache和nginx使用basic auth https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication