package main import ( "database/sql" "encoding/json" "fmt" "log" "net/http" "strconv" "strings" "time" "github.com/gin-gonic/gin" _ "github.com/go-sql-driver/mysql" ) var StoreStreamer *sql.DB var SqlQuery string = `SELECT ie.uid, ie.platform, ie.user_id, ie.user_name , ie.live_url , ie.tags , cl.followers , cl.views , cl.gratuity , cl.live_title, cl.live_start_time , cl.live_end_time , cl.update_time From ( SELECT * FROM intimate_extractor.streamer WHERE platform = "twitcasting" AND operator = 0 AND latest_log_uid is not NULL limit %s,%s) ie JOIN intimate_extractor.collect_log cl WHERE ie.latest_log_uid = cl.log_uid; ` func init() { db, err := sql.Open("mysql", InitConfig.Database.ExtractorURI) if err != nil { panic(err) } StoreStreamer = db } // ie.uid, // ie.platform, // ie.user_id, // ie.user_name , // ie.live_url , // ie.tags , // cl.followers , // cl.views , // cl.gratuity , // cl.live_title, // cl.live_start_time , // cl.live_end_time , // cl.update_time type ObjectTwistcasting struct { Uid int64 Platform string UserId string UserName string LiveUrl string Tags []string Followers int64 Views int64 Gratuity int64 LiveTitle string LiveStartTime *time.Time LiveEndTime *time.Time UpdateTime *time.Time } type Result struct { Code int Error string Data interface{} } func TwitcastingQuery(cxt *gin.Context) { var err error page, err := strconv.Atoi(cxt.Query("page")) if err != nil { cxt.Error(err) } psize, err := strconv.Atoi(cxt.Query("psize")) if err != nil { cxt.Error(err) } if psize > 100 { cxt.Error(fmt.Errorf("page size <= 100")) } start := (page - 1) * 200 // end := start + 200 ssql := fmt.Sprintf(SqlQuery, strconv.Itoa(start), strconv.Itoa(psize)) rows, err := StoreStreamer.Query(ssql) if err != nil { cxt.Error(err) } var ots []*ObjectTwistcasting for rows.Next() { ot := &ObjectTwistcasting{} var lstm, letm, utm sql.NullTime var tags string err = rows.Scan( &ot.Uid, &ot.Platform, &ot.UserId, &ot.UserName, &ot.LiveUrl, &tags, &ot.Followers, &ot.Views, &ot.Gratuity, &ot.LiveTitle, &lstm, &letm, &utm, ) if err != nil { cxt.Error(err) return } if !lstm.Valid { ot.LiveStartTime = nil } else { ot.LiveStartTime = &lstm.Time } if !letm.Valid { ot.LiveEndTime = nil } else { ot.LiveEndTime = &letm.Time } if !utm.Valid { ot.UpdateTime = nil } else { ot.UpdateTime = &utm.Time } if err = json.Unmarshal([]byte(tags), &ot.Tags); err != nil { log.Println(tags) } ots = append(ots, ot) } r := &Result{Code: 200} r.Data = ots log.Println(len(ots)) if retdata, err := json.Marshal(r); err != nil { cxt.Error(err) } else { cxt.JSON(r.Code, string(retdata)) } } func Cors() gin.HandlerFunc { return func(c *gin.Context) { method := c.Request.Method //请求方法 origin := c.Request.Header.Get("Origin") //请求头部 var headerKeys []string // 声明请求头keys for k, _ := range c.Request.Header { headerKeys = append(headerKeys, k) } headerStr := strings.Join(headerKeys, ", ") if headerStr != "" { headerStr = fmt.Sprintf("access-control-allow-origin, access-control-allow-headers, %s", headerStr) } else { headerStr = "access-control-allow-origin, access-control-allow-headers" } if origin != "" { c.Writer.Header().Set("Access-Control-Allow-Origin", "*") c.Header("Access-Control-Allow-Origin", "*") // 这是允许访问所有域 c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE,UPDATE") //服务器支持的所有跨域请求的方法,为了避免浏览次请求的多次'预检'请求 // header的类型 c.Header("Access-Control-Allow-Headers", "Authorization, Content-Length, X-CSRF-Token, Token,session,X_Requested_With,Accept, Origin, Host, Connection, Accept-Encoding, Accept-Language,DNT, X-CustomHeader, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, Pragma") // 允许跨域设置 可以返回其他子段 c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers,Cache-Control,Content-Language,Content-Type,Expires,Last-Modified,Pragma,FooBar") // 跨域关键设置 让浏览器可以解析 c.Header("Access-Control-Max-Age", "172800") // 缓存请求信息 单位为秒 c.Header("Access-Control-Allow-Credentials", "false") // 跨域请求是否需要带cookie信息 默认设置为true c.Set("content-type", "application/json") // 设置返回格式是json } //放行所有OPTIONS方法 if method == "OPTIONS" { c.JSON(http.StatusOK, "Options Request!") } // 处理请求 c.Next() // 处理请求 } } func main() { engine := gin.New() //r := gin.Default() //使用默认中间件 engine.Use(gin.Logger()) engine.Use(Cors()) engine.GET("twitcasting/query", TwitcastingQuery) engine.Run(":5500") }