net/http

http 包實現(xiàn)了http客戶端與服務端的實現(xiàn)

  • 1.創(chuàng)建http客戶端
  • 2.客戶端發(fā)起get,post,postForm請求演示
  • 3.自定義客戶端請求
  • 4.創(chuàng)建服務端
  • 5.自定義服務端配置
  • 6.解析HTTP版本號
  • 7.將不同格式的時間字符串,轉換成標準time結構
  • 8.獲取http狀態(tài)碼Status 對應的文本信息
  • 9.監(jiān)測服務器與客戶端的連接狀態(tài)
  • 10.獲取請求頭里面的數(shù)據(jù)
  • 11.將請求頭的數(shù)據(jù)寫入文件中
  • 12.文件服務器創(chuàng)建
  • 13.請求重定向演示
  • 14.將文件的內容返回給請求
  • 15.建立https服務
  • 16.接管服務器和客戶端連接

1.創(chuàng)建http客戶端

客戶端請求連接過程

1 創(chuàng)建http客戶端對象
2 按照指定方式請求數(shù)據(jù)
3 獲取數(shù)據(jù)
4 關閉連接

type Client struct {
      
         // 傳輸機制
    Transport RoundTripper

    // CheckRedirect 指定了重定向策略.
    CheckRedirect func(req *Request, via []*Request) error

    // Jar 指定了緩存
    Jar CookieJar

       // 設定了超時時間
    Timeout time.Duration
}

var DefaultClient = &Client{}
DefaultClient提供了Get级野、Head铣鹏、Post 的默認Client.

import (
    "net/http"
    "log"
    "io/ioutil"
    "fmt"
)

func main() {
  // 創(chuàng)建客戶端發(fā)get請求
   resp,error := http.DefaultClient.Get("http://example.com/")
 // 相應結束后,請及時關閉會話
   defer resp.Body.Close()
   if error != nil {
       log.Fatal(error)
   }
   // 讀取相應的數(shù)據(jù)
   data,error := ioutil.ReadAll(resp.Body)
   fmt.Println(string(data))
 }

我們看一下響應數(shù)據(jù)結構體都包含了那些數(shù)據(jù)

type Response struct {
    Status     string // e.g. "200 OK"
    StatusCode int    // e.g. 200
    Proto      string // e.g. "HTTP/1.0"
    ProtoMajor int    // e.g. 1
    ProtoMinor int    // e.g. 0
    Header Header  // 相應頭部
    Body io.ReadCloser
    ContentLength int64 // 內容長度
    TransferEncoding []string // 傳輸數(shù)據(jù)編碼
    Close bool // 是否關閉連接
        Uncompressed bool //是否未壓縮
    Trailer Header
    Request *Request // 原始請求相關
    TLS *tls.ConnectionState // https 加密相關
}

2.客戶端發(fā)起get,post,postForm請求演示

resp, err := http.Get("http://example.com/")
...
resp, err := http.Post("http://example.com/upload", "image/jpeg", &buf)
...
resp, err := http.PostForm("http://example.com/form",
    url.Values{"key": {"Value"}, "id": {"123"}})

3.自定義客戶端請求

  • 定義請求方式
  • 定義請求重定向策略
  • 自定義請求頭
  • 自定義Transport
  • TLS配置

我們就針對上面的5點進行演示

定義請求方式:除了系統(tǒng)提供默認的創(chuàng)建客戶端的方式,我們也可以手動創(chuàng)建客戶端吩抓,比較簡單沈条,直接看下面的例子

package main

import (
    "net/http"
    "log"
    "io/ioutil"
    "fmt"
)

func main() {
   // 創(chuàng)建一個客戶端
   client := &http.Client{}

   // 創(chuàng)建一個自定義請求
   req,_:= http.NewRequest("Get","http://www.baidu.com",nil)

   // 讓客戶端執(zhí)行請求
   resp,error := client.Do(req)
  // 關閉請求
  defer resp.Body.Close()
   if error != nil {
       log.Fatal(error)
   }
   data,error := ioutil.ReadAll(resp.Body)
   fmt.Println(string(data))
 }
請求數(shù)據(jù)的截圖

定義請求策略:如果我們不設置請求重定向策略,系統(tǒng)會使用默認的重定向策略

package main

import (
    "net/http"
    "log"
        "fmt"
    "io/ioutil"
)

func main() {
   // 創(chuàng)建一個客戶端
   client := &http.Client{
       CheckRedirect:CheckRedirect,
   }
   // 創(chuàng)建一個自定義請求
   req,_:= http.NewRequest("Get","http://www.baidu.com",nil)

   // 讓客戶端執(zhí)行請求
   resp,error := client.Do(req)
   defer resp.Body.Close()
   if error != nil {
       log.Fatal(error)
   }
   fmt.Println(resp.StatusCode)
   data,error := ioutil.ReadAll(resp.Body)
   fmt.Println(string(data))

 }

func CheckRedirect(req *http.Request, via []*http.Request) error{
    fmt.Println(req.URL.Host)
    if req.URL.Host == "www.baidu.com" {
        // 返回http.ErrUseLastResponse 可以禁止重定向
        return  http.ErrUseLastResponse
    }
    return nil
}
image.png

自定義請求頭

client := &http.Client{
    CheckRedirect: redirectPolicyFunc,
}
resp, err := client.Get("http://example.com")
// ...
req, err := http.NewRequest("GET", "http://example.com", nil)
// ...
req.Header.Add("If-None-Match", `W/"wyzzy"`)

自定義Transport 要管理代理曼玩、TLS配置、keep-alive岛琼、壓縮和其他設置雏逾,創(chuàng)建一個Transport

tr := &http.Transport{
    TLSClientConfig:    &tls.Config{RootCAs: pool},
    DisableCompression: true,
}
client := &http.Client{Transport: tr}

4.創(chuàng)建服務器

簡單的請求

func ListenAndServe(addr string, handler Handler) error

參數(shù) Handler 是一個接口類型,需要我們實現(xiàn)下面的接口

type Handler interface {
    ServeHTTP(ResponseWriter, *Request)
}

下面我們看一個完整的例子

package main
import (
    "net/http"
    "fmt"
    )

// 第一步 Handle 實現(xiàn)接口
type  Controller struct {
}

func (c Controller)ServeHTTP(resp http.ResponseWriter, req *http.Request){
    fmt.Println(req.Host)
    resp.Write([]byte("我是服務器返回的數(shù)據(jù)"))
    req.Body.Close()
}

func main() {
   // 第二步 監(jiān)聽服務
   http.ListenAndServe(":8081",&Controller{})
 }

我們在http請求的時候,往往需要處理不同的請求路徑,比如/login 和/register ,go為我們提供了如下的方法進行處理

func HandleFunc(pattern string, handler func(ResponseWriter, *Request))
func Handle(pattern string, handler Handler)

路由匹配

package main

import (
    "net/http"
    "fmt"
    )

func main() {
  // 第一步 注冊請求匹配函數(shù)
  http.HandleFunc("/login", func(writer http.ResponseWriter, request *http.Request) {
      fmt.Println(request.Host)
      fmt.Println(request.URL)
      fmt.Println(request.URL.RawQuery)
      fmt.Println(request.Body)
      fmt.Println(request.Header)
      // 服務器相應數(shù)據(jù)
      writer.Write([]byte(request.UserAgent()))
      request.Body.Close()
  })
  // 監(jiān)聽服務
  http.ListenAndServe(":8081",nil)
 }

func Handle(pattern string, handler Handler) 需要自己創(chuàng)建變量實現(xiàn) handle接口,實現(xiàn)的過程我們已經(jīng)演示過了,就不在贅述了

5.自定義服務端配置

上面我們使用 http.ListenAndServe 啟動了一個監(jiān)聽服務,但是我們在實際使用的過程中,有時需要配置一些信息比如

  • 讀請求的最大時間
  • 寫入的組大時間
  • 最大的頭字節(jié)數(shù)
    ...

下面我們就演示一下如何實現(xiàn)自定義服務端配置的過程

package main

import (
    "net/http"
    "fmt"
    "time"
)

type  Controller struct {
}

func (c Controller)ServeHTTP(resp http.ResponseWriter, req *http.Request){
    fmt.Println(req.Host)
    resp.Write([]byte("我是服務器返回的數(shù)據(jù)"))
    req.Body.Close()
}

func main() {
  //// 監(jiān)聽服務
  server := http.Server{
      Addr:           ":8080",
      Handler:        &Controller{},
      ReadTimeout:    10 * time.Second,
      WriteTimeout:   10 * time.Second,
      MaxHeaderBytes: 1 << 20,
  }
  server.ListenAndServe()
 }

瀏覽器輸入 http://localhost:8080

服務器日志
瀏覽器接受數(shù)據(jù)

6.解析HTTP 版本號

func ParseHTTPVersion(vers string) (major, minor int, ok bool)

    fmt.Println(http.ParseHTTPVersion("HTTP/1.0"))
image.png

7.將不同格式的時間字符串,轉換成標準time結構

func ParseTime(text string) (t time.Time, err error)

    t,_ := http.ParseTime("Monday, 02-Jan-06 15:04:05 MST") // time.RFC850
    fmt.Println(t)
    t,_ = http.ParseTime("Mon Jan 2 15:04:05 2006")  //time.ANSIC 不能使用字符_
    fmt.Println(t)

日志:

2006-01-02 15:04:05 +0000 MST
2006-01-02 15:04:05 +0000 UTC

8.獲取http狀態(tài)碼Status 對應的文本信息

func StatusText(code int) string

  fmt.Println(http.StatusText(200))
  fmt.Println(http.StatusText(301))
    fmt.Println(http.StatusText(500))

OK
Moved Permanently
Internal Server Error


9.監(jiān)測服務器與客戶端的連接狀態(tài)

type ConnState int

const (
    // StateNew代表一個新的連接,將要立刻發(fā)送請求廊驼。
    // 連接從這個狀態(tài)開始据过,然后轉變?yōu)镾tateAlive或StateClosed。
    StateNew ConnState = iota
    // StateActive代表一個已經(jīng)讀取了請求數(shù)據(jù)1到多個字節(jié)的連接。
    // 用于StateAlive的Server.ConnState回調函數(shù)在將連接交付給處理器之前被觸發(fā),
    // 等到請求被處理完后馁菜,Server.ConnState回調函數(shù)再次被觸發(fā)鸿秆。
    // 在請求被處理后幅聘,連接狀態(tài)改變?yōu)镾tateClosed、StateHijacked或StateIdle。
    StateActive
    // StateIdle代表一個已經(jīng)處理完了請求、處在閑置狀態(tài)原朝、等待新請求的連接。
    // 連接狀態(tài)可以從StateIdle改變?yōu)镾tateActive或StateClosed镶苞。
    StateIdle
    // 代表一個被劫持的連接喳坠。這是一個終止狀態(tài),不會轉變?yōu)镾tateClosed茂蚓。
    StateHijacked
    // StateClosed代表一個關閉的連接壕鹉。
    // 這是一個終止狀態(tài)。被劫持的連接不會轉變?yōu)镾tateClosed煌贴。
    StateClosed
)
package main

import (
    "net/http"
    "fmt"
    "time"
    "net"
)

type  Controller struct {
}

func (c Controller)ServeHTTP(resp http.ResponseWriter, req *http.Request){
    fmt.Println(req.Host)
    resp.Write([]byte("我是服務器返回的數(shù)據(jù)"))
    req.Body.Close()
}

func main() {
  //// 監(jiān)聽服務
  server := http.Server{
      Addr:           ":8080",
      Handler:        &Controller{},
      ReadTimeout:    10 * time.Second,
      WriteTimeout:   10 * time.Second,
      MaxHeaderBytes: 1 << 1,
  }

  // 監(jiān)測服務器的連接狀態(tài)
  server.ConnState = func(conn net.Conn, state http.ConnState) {
      fmt.Println(state)
  }

  server.ListenAndServe()

 }
image.png

我們發(fā)現(xiàn)瀏覽器想服務器發(fā)送請求兩次請求,但是只有一個closed狀態(tài),這個是因為一旦服務器與瀏覽器完成數(shù)據(jù)交互后,連接狀態(tài)還是激活狀態(tài),沒有關閉,如果在最大連接時間未到時,客戶端繼續(xù)發(fā)送請求御板,就不會要重新建立連接了锥忿。如果我們想要每次數(shù)據(jù)結束后立即關閉連接牛郑,使用下面的方法即可

server.SetKeepAlivesEnabled(false)

image.png

10.獲取請求頭里面的數(shù)據(jù)

    for key,value := range req.Header{
        fmt.Println(key,":",value)
    }

Accept-Encoding : [gzip, deflate]
Connection : [keep-alive]
Upgrade-Insecure-Requests : [1]
Cookie : [pgv_pvi=4726842368; Webstorm-7b1b8ce4=a417cfae-a0df-4fa4-96a0-bec5a8aa3f22; _ga=GA1.1.1767641313.1490064708; Phpstorm-854b20c0=cce12517-63b4-48f0-8a05-1f6156ee2339]
User-Agent : [Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Safari/605.1.15]
Accept-Language : [zh-cn]
Accept : [text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8]

獲取指定key的對應的值

req.Header.Get("key")

設置添加值到header中,如鍵已存在則會用只有新值一個元素的切片取代舊值切片

req.Header.Set("key","value")

Add添加鍵值對到h,如鍵已存在則會將新的值附加到舊值切片后面

func (h Header) Add(key, value string)

刪除請求頭數(shù)據(jù)

func (h Header) Del(key string)

11.將請求頭的數(shù)據(jù)寫入文件中

// Write以有線格式將頭域寫入w
func (h Header) Write(w io.Writer) error 
//WriteSubset以有線格式將頭域寫入w敬鬓。當exclude不為nil時淹朋,如果h的鍵值對的鍵在exclude中存在且其對應值為真笙各,該鍵值對就不會被寫入w
func (h Header) WriteSubset(w io.Writer, exclude map[string]bool) error

示例 1

    file,_ := os.Create("/Users/xujie/go/src/awesomeProject/main/header.txt")
    req.Header.Write(file)
image.png

示例 2

    file,_ := os.Create("/Users/xujie/go/src/awesomeProject/main/header.txt")
    req.Header.WriteSubset(file,map[string]bool{"Accept":true})
image.png

通過方法 WriteSubset我們將header寫入文件時,過濾了 Accept


12.文件服務器創(chuàng)建

func FileServer(root FileSystem) Handler

    http.Handle("/login",&Controller{})
    http.Handle("/",http.FileServer(http.Dir("/usr/local")))
    http.ListenAndServe(":8080",nil)

訪問 http://localhost:8080 即可查看

image.png

這里注意一下 我們的注冊 http.Handle("/",http.FileServer(http.Dir("/usr/local"))),如果我們想要給我們可訪問目錄設置一個別名,不讓用戶直接訪問該怎么處理呢?

 http.Handle("/public",http.StripPrefix("/public",http.FileServer(http.Dir("/usr/local"))))
 http.ListenAndServe(":8080",nil)

接下來就可以通過 http://localhost:8080/public 進行訪問了


13.請求重定向演示

如果我們訪問一個頁面出現(xiàn)了錯誤,我們讓用戶重定向到一個其他頁面上,類似于這個過程就是重定向

func Redirect(w ResponseWriter, r *Request, urlStr string, code int)

示例

package main

import (
    "net/http"
          )

type  Controller struct {
}
func (c Controller)ServeHTTP(resp http.ResponseWriter, req *http.Request){
    // 請求重定向
    http.Redirect(resp,req,"/error",http.StatusMovedPermanently)
}
func main() {
    //// 監(jiān)聽服務
    http.Handle("/login",&Controller{})
    http.HandleFunc("/error", func(writer http.ResponseWriter, request *http.Request) {
        writer.Write([]byte("重定向的錯誤頁面"))
    })
    http.ListenAndServe(":8080",nil)
 }

當我們?yōu)g覽器訪問http://localhost/login ,服務器會重定向到/error 對應的服務上,這個時候瀏覽器的輸入欄的地址也會自動切換到http://localhost/error

image.png

如果想直接返回未找到資源的信息提示,可以使用

func NotFound(w ResponseWriter, r *Request)

將文件的內容返回給請求

  • 全部返回
package main
import (
    "net/http"
)
type  Controller struct {
}
func (c Controller)ServeHTTP(resp http.ResponseWriter, req *http.Request){
    http.ServeFile(resp,req,"/Users/xujie/go/src/awesomeProject/main/private.pem")
}
func main() {
  //// 監(jiān)聽服務
    http.Handle("/private",&Controller{})
    http.ListenAndServe(":8080",nil)
 }
image.png

15.建立https服務

ListenAndServeTLS函數(shù)和ListenAndServe函數(shù)的行為基本一致础芍,除了它期望HTTPS連接之外杈抢。此外,必須提供證書文件和對應的私鑰文件仑性。如果證書是由權威機構簽發(fā)的惶楼,certFile參數(shù)必須是順序串聯(lián)的服務端證書和CA證書。如果srv.Addr為空字符串诊杆,會使用":https"

我們先生成 cert.pem和key.pem

package main

import (
    "bytes"
    cryptorand "crypto/rand"
    "crypto/rsa"
    "crypto/x509"
    "crypto/x509/pkix"
    "encoding/pem"
    "fmt"
    "math/big"
    "net"
    "time"
)

func main() {
    ip := []byte("192.168.110.66")
    alternateDNS := []string{"kubernetes.default.svc", "kubernetes.default", "kubernetes", "localhost"}
    cert, key, _ := GenerateSelfSignedCertKey("10.10.10.10", []net.IP{ip}, alternateDNS)
    fmt.Println(string(cert), string(key))

}

func GenerateSelfSignedCertKey(host string, alternateIPs []net.IP, alternateDNS []string) ([]byte, []byte, error) {
    priv, err := rsa.GenerateKey(cryptorand.Reader, 2048)
    if err != nil {
        return nil, nil, err
    }

    template := x509.Certificate{
        SerialNumber: big.NewInt(1),
        Subject: pkix.Name{
            CommonName: fmt.Sprintf("%s@%d", host, time.Now().Unix()),
        },
        NotBefore: time.Now(),
        NotAfter:  time.Now().Add(time.Hour * 24 * 365),

        KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
        ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
        BasicConstraintsValid: true,
        IsCA: true,
    }

    if ip := net.ParseIP(host); ip != nil {
        template.IPAddresses = append(template.IPAddresses, ip)
    } else {
        template.DNSNames = append(template.DNSNames, host)
    }

    template.IPAddresses = append(template.IPAddresses, alternateIPs...)
    template.DNSNames = append(template.DNSNames, alternateDNS...)

    derBytes, err := x509.CreateCertificate(cryptorand.Reader, &template, &template, &priv.PublicKey, priv)
    if err != nil {
        return nil, nil, err
    }

    // Generate cert
    certBuffer := bytes.Buffer{}
    if err := pem.Encode(&certBuffer, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}); err != nil {
        return nil, nil, err
    }

    // Generate key
    keyBuffer := bytes.Buffer{}
    if err := pem.Encode(&keyBuffer, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)}); err != nil {
        return nil, nil, err
    }

    return certBuffer.Bytes(), keyBuffer.Bytes(), nil
}

命令行生成

openssl genrsa -out ca.key 2048 生成root密鑰
openssl req -new -x509 -sha256 -key ca.key -days 3650 -out ca.crt -subj "/CN=dotcoo.com" 生成root簽名
openssl genrsa -out server.key 2048 生成server密鑰
openssl req -new -sha256 -key server.key -subj "/CN=server.com" -out server.csr 生成server簽名請求
openssl x509 -req -sha256 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 3650 給server簽名
openssl x509 -in ./server.crt -noout -text 查詢狀態(tài)
image.png

接下來我們就可以使用https訪問我們的本地服務了

package main

import (
    "net/http"
    "log"
)

type  Controller struct {

}

func (c Controller)ServeHTTP(resp http.ResponseWriter, req *http.Request){
   resp.Write([]byte("返回數(shù)據(jù)"))
}

func main() {
  //// 監(jiān)聽服務
    http.Handle("/private",&Controller{})
    err := http.ListenAndServeTLS(":10443","/Users/xujie/go/src/awesomeProject/server.crt","/Users/xujie/go/src/awesomeProject/server.key",nil)
    if err != nil {
        log.Fatal(err)
    }
 }
image.png

如果你任然使用http訪問就會發(fā)生錯誤

2018/09/27 17:28:30 http: TLS handshake error from [::1]:59181: tls: first record does not look like a TLS handshake

16.接管服務器和客戶端連接

type Hijacker interface {
    // Hijack讓調用者接管連接歼捐,返回連接和關聯(lián)到該連接的一個緩沖讀寫器。
    // 調用本方法后晨汹,HTTP服務端將不再對連接進行任何操作豹储,
    // 調用者有責任管理、關閉返回的連接淘这。
    Hijack() (net.Conn, *bufio.ReadWriter, error)
}
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末剥扣,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子铝穷,更是在濱河造成了極大的恐慌钠怯,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,525評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件曙聂,死亡現(xiàn)場離奇詭異呻疹,居然都是意外死亡,警方通過查閱死者的電腦和手機筹陵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評論 3 395
  • 文/潘曉璐 我一進店門刽锤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人朦佩,你說我怎么就攤上這事并思。” “怎么了语稠?”我有些...
    開封第一講書人閱讀 164,862評論 0 354
  • 文/不壞的土叔 我叫張陵宋彼,是天一觀的道長。 經(jīng)常有香客問我仙畦,道長输涕,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,728評論 1 294
  • 正文 為了忘掉前任慨畸,我火速辦了婚禮莱坎,結果婚禮上,老公的妹妹穿的比我還像新娘寸士。我一直安慰自己檐什,他們只是感情好碴卧,可當我...
    茶點故事閱讀 67,743評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著乃正,像睡著了一般住册。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上瓮具,一...
    開封第一講書人閱讀 51,590評論 1 305
  • 那天荧飞,我揣著相機與錄音,去河邊找鬼名党。 笑死垢箕,一個胖子當著我的面吹牛,可吹牛的內容都是我干的兑巾。 我是一名探鬼主播条获,決...
    沈念sama閱讀 40,330評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼蒋歌!你這毒婦竟也來了帅掘?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,244評論 0 276
  • 序言:老撾萬榮一對情侶失蹤堂油,失蹤者是張志新(化名)和其女友劉穎修档,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體府框,經(jīng)...
    沈念sama閱讀 45,693評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡吱窝,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,885評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了迫靖。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片院峡。...
    茶點故事閱讀 40,001評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖系宜,靈堂內的尸體忽然破棺而出照激,到底是詐尸還是另有隱情,我是刑警寧澤盹牧,帶...
    沈念sama閱讀 35,723評論 5 346
  • 正文 年R本政府宣布俩垃,位于F島的核電站,受9級特大地震影響汰寓,放射性物質發(fā)生泄漏口柳。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,343評論 3 330
  • 文/蒙蒙 一有滑、第九天 我趴在偏房一處隱蔽的房頂上張望跃闹。 院中可真熱鬧,春花似錦、人聲如沸辣卒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽荣茫。三九已至,卻和暖如春场靴,著一層夾襖步出監(jiān)牢的瞬間啡莉,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評論 1 270
  • 我被黑心中介騙來泰國打工旨剥, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留咧欣,地道東北人。 一個月前我還...
    沈念sama閱讀 48,191評論 3 370
  • 正文 我出身青樓轨帜,卻偏偏與公主長得像魄咕,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子蚌父,可洞房花燭夜當晚...
    茶點故事閱讀 44,955評論 2 355

推薦閱讀更多精彩內容

  • 2017年8月12日 星期六 晴 今天我去參加捐書活動哮兰。我們...
    晨晨_d5f3閱讀 240評論 0 3
  • 之前佐羅就聽到有傳聞說Tether要增發(fā)USDT膏秫,沒想到那么快就真的來了右遭。USDT一直都作為市場的春藥,發(fā)行USD...
    程序員佐羅嗨幣手記閱讀 436評論 0 0
  • 蘇州行聽鄭清元的課程缤削,名額緊張窘哈,經(jīng)過努力終于收到了公司的邀請,謝謝各領導的推薦Mじ摇宵距!公司給各代理安排了豪華的酒...
    葉子_5f0a閱讀 553評論 0 0
  • 購物這件事也是有不同的國情。 雖然自己并非購物的熱衷者吨拗,卻也知道逛街購物是女人的一大愛好满哪。姐妹們約起,隨意走走劝篷,喝...
    XinSuting閱讀 391評論 0 0