Full Code of wyh267/shortService for AI

master f330724b84f9 cached
18 files
19.2 KB
6.1k tokens
58 symbols
1 requests
Download .txt
Repository: wyh267/shortService
Branch: master
Commit: f330724b84f9
Files: 18
Total size: 19.2 KB

Directory structure:
gitextract__l2jne5p/

├── .gitignore
├── README.md
├── config.ini
├── install.sh
├── src/
│   ├── shortService/
│   │   ├── CountThread.go
│   │   ├── OriginalProcessor.go
│   │   ├── Server.go
│   │   └── ShortProcessor.go
│   └── shortlib/
│       ├── Configure.go
│       ├── LRU.go
│       ├── LRU_test.go
│       ├── Processor.go
│       ├── RedisAdaptor.go
│       ├── Router.go
│       └── Utils.go
├── start.sh
├── stop.sh
└── test.sh

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
*.o
*.swp
*github.com*
*bin/
*pkg/
*.log*
*jzlservice/
.DS_Store
nohup.out


================================================
FILE: README.md
================================================

## 短链接服务

#### 短连接的原理

很多人一定想的是**短连接是通过一定的算法将长链接变成短连接的,然后访问的时候再还原**,恩,非常高大上,但是仔细想想,怎么可能,那得多牛逼的压缩算法,多长的url都可以压缩为几个字节,而且还能还原,还是无损压缩。

所以,实际上,短连接生成核心就两个字:**数数**,就是不停的自增一个数,然后有个表保存每个数和原始链接的对应关系,访问短连接的时候将原是连接取出来。

知道了原理就好弄了,最简单的办法,就是用一个数组来存储,数组的索引就是短链接,数组的值就是原始链接,恩,完美,由于数组下标是短链接,那么获取短链接的时间复杂度是O(1),同时生成短链接的时间复杂度也是O(1)

#### 短链接服务的实现

实现一个短链接服务,用数组固然可能,但也显得太LOW了吧,所以为了实现这个服务,从以下几个部分来实现。

首先,给两个概念

- **解析短链接**,就是请求是短连接,返回一个跳转的原始链接
- **生成短链接**,就是有个长链接,返回生成的短链接

##### 存储

持久化的部分使用Redis数据库来实现,很明显,key-value的结构很适合存在Redis中
这部分主要在 shortlib/RedisAdaptor.go中

##### 计数器

数数的功能可以用Redis的自增功能实现,这样也保证了原子性,同样这部分也可以自己实现,因为go语言开线程很容易,专门开一个线程实现这个功能,通过channl来接受请求,保证是串行的就行了,不就是数数嘛,大家都会
这部分在shortlib/RedisAdaptor.go和shortService/CountThread.go中,具体实现的时候通过配置文件的参数,返回一个高阶函数,调用的时候自动分配到不同的函数实现。

##### 缓存服务

Redis固然很快,但是我们还需要更快,要是热门数据存在内存中就更快了,而且还有个问题,就是热门的url要是有人不停的申请短连接会造成浪费,为了防止这个问题,自己实现了一个LRU模块,解析短链接的时候,命中了话直接返回结果,否则从Redis返回数据,如果是申请短链接的话,如果在LRU中,那不再重新生成短链接了。
这部分主要在 shortlib/LRU.go中。

##### 对外服务

这一部分用的go的http框架,很容易实现高并发,没啥好说的,现在编程高并发不是问题了,连语言都自带这框架了。
这部分包括shortlib/Router.go , shortService/OriginalProcessor.go,shortService/ShortProcessor.go 这几个文件。


================================================
FILE: config.ini
================================================

[server]
port = 26719
hostname = http://t.cn/ #前缀域名

[service]
threads = 200
counter = redis # inner 使用内部还是Redis进行计数


[redis]
redishost = 10.254.33.20
redisport = 32079
status = false # 是否初始化Redis计数器



================================================
FILE: install.sh
================================================
#!/bin/zsh

go install shortService


================================================
FILE: src/shortService/CountThread.go
================================================
/*************************************************************************
	> File Name: CountThread.go
	> Author: Wu Yinghao
	> Mail: wyh817@gmail.com
	> Created Time: 一  6/15 16:19:18 2015
 ************************************************************************/

package main

import (
	//	"fmt"
	"shortlib"
)

func CountThread(count_chan_in chan shortlib.CountChannl) {

	var count int64
	count = 1000
	for {
		select {
		case ok := <-count_chan_in:
			count = count + 1
			ok.CountOutChan <- count

		}

	}
}


================================================
FILE: src/shortService/OriginalProcessor.go
================================================
/*************************************************************************
	> File Name: OriginalProcessor.go
	> Author: Wu Yinghao
	> Mail: wyh817@gmail.com
	> Created Time: 日  6/14 16:00:54 2015
 ************************************************************************/

package main

import (
	"encoding/json"
	"errors"
	"io"
	"net/http"
	"shortlib"
)

type OriginalProcessor struct {
	*shortlib.BaseProcessor
	Count_Channl chan shortlib.CountChannl
}

const POST string = "POST"
const TOKEN string = "token"
const ORIGINAL_URL string = "original"
const SHORT_URL string = "short"

/*
*
*
*
{
	"original" : "http://XX.XX.com/XXTTYD",
	"token" : "DFEdafaeaqh43da"
}
*
*
*/
func (this *OriginalProcessor) ProcessRequest(method, request_url string, params map[string]string, body []byte, w http.ResponseWriter, r *http.Request) error {
	if method != POST {
		return errors.New("Create short url must be POST the information")
	}
	var bodyInfo map[string]interface{}
	err := json.Unmarshal(body, &bodyInfo)
	if err != nil {
		return err
	}

	token, has_token := bodyInfo[TOKEN].(string)
	original_url, has_original_url := bodyInfo[ORIGINAL_URL].(string)

	if !has_token || !has_original_url {
		return errors.New("Post info errors")
	}

	if !shortlib.IsAllowToken(token) {
		return errors.New("Token is not allow")
	}

	if !shortlib.IsNormalUrl(original_url) {
		return errors.New("Url is not normal")
	}

	short_url, err := this.createUrl(original_url)
	if err != nil {
		return err
	}

	response, err := this.createResponseJson(short_url)
	if err != nil {
		return err
	}

	//add head information
	header := w.Header()
	header.Add("Content-Type", "application/json")
	header.Add("charset", "UTF-8")
	io.WriteString(w, response)

	return nil
}

//
//生成short url
//
//
func (this *OriginalProcessor) createUrl(original_url string) (string, error) {

	short, err := this.Lru.GetShortURL(original_url)
	if err == nil {
		//		fmt.Printf("[INFO] Match the short url : %v ===> %v\n",original_url,short)
		return short, nil
	}
	/*
		count, err := this.RedisCli.NewShortUrlCount()
		if err != nil {
			return "", err
		}

		count_c := make(chan int64)
		ch:=shortlib.CountChannl{0,count_c}
		this.Count_Channl <- ch
		count := <- count_c
	*/

	count, err := this.CountFunction()
	if err != nil {
		return "", err
	}
	short_url, err := shortlib.TransNumToString(count)
	if err != nil {
		return "", err
	}
	//将对应关系添加到LRU缓存中
	this.Lru.SetURL(original_url, short_url)
	return short_url, nil

}

func (this *OriginalProcessor) createResponseJson(short_url string) (string, error) {

	json_res := make(map[string]interface{})
	json_res[SHORT_URL] = this.HostName + short_url

	res, err := json.Marshal(json_res)
	if err != nil {
		return "", err
	}

	return string(res), nil
}


================================================
FILE: src/shortService/Server.go
================================================
/*************************************************************************
	> File Name: Server.go
	> Author: Wu Yinghao
	> Mail: wyh817@gmail.com
	> Created Time: 日  6/14 16:00:54 2015
 ************************************************************************/

package main

import (
	"flag"
	"fmt"
	"net/http"
	"os"
	"shortlib"
)

func main() {
	var configFile string
	flag.StringVar(&configFile, "conf", "config.ini", "configure file full path")
	flag.Parse()

	//读取配置文件
	fmt.Printf("[INFO] Read configure file...\n")
	configure, err := shortlib.NewConfigure(configFile)
	if err != nil {
		fmt.Printf("[ERROR] Parse Configure File Error: %v\n", err)
		return
	}

	//启动Redis客户端
	fmt.Printf("[INFO] Start Redis Client...\n")
	redis_cli, err := shortlib.NewRedisAdaptor(configure)
	if err != nil {
		fmt.Printf("[ERROR] Redis init fail..\n")
		return
	}
	//是否初始化Redis计数器,如果为ture就初始化计数器
	if configure.GetRedisStatus() {
		err = redis_cli.InitCountService()
		if err != nil {
			fmt.Printf("[ERROR] Init Redis key count fail...\n")
		}
	}

	//不使用redis的情况下,启动短链接计数器
	count_channl := make(chan shortlib.CountChannl, 1000)
	go CountThread(count_channl)

	countfunction := shortlib.CreateCounter(configure.GetCounterType(), count_channl, redis_cli)
	//启动LRU缓存
	fmt.Printf("[INFO] Start LRU Cache System...\n")
	lru, err := shortlib.NewLRU(redis_cli)
	if err != nil {
		fmt.Printf("[ERROR]LRU init fail...\n")
	}
	//初始化两个短连接服务
	fmt.Printf("[INFO] Start Service...\n")
	baseprocessor := &shortlib.BaseProcessor{redis_cli, configure, configure.GetHostInfo(), lru, countfunction}

	original := &OriginalProcessor{baseprocessor, count_channl}
	short := &ShortProcessor{baseprocessor}

	//启动http handler
	router := &shortlib.Router{configure, map[int]shortlib.Processor{
		0: short,
		1: original,
	}}

	//启动服务

	port, _ := configure.GetPort()
	addr := fmt.Sprintf(":%d", port)
	fmt.Printf("[INFO]Service Starting addr :%v,port :%v\n", addr, port)
	err = http.ListenAndServe(addr, router)
	if err != nil {
		//logger.Error("Server start fail: %v", err)
		os.Exit(1)
	}

}


================================================
FILE: src/shortService/ShortProcessor.go
================================================
/*************************************************************************
	> File Name: ShortProcessor.go
	> Author: Wu Yinghao
	> Mail: wyh817@gmail.com
	> Created Time: 日  6/14 16:00:54 2015
 ************************************************************************/

package main

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

type ShortProcessor struct {
	*shortlib.BaseProcessor
}

func (this *ShortProcessor) ProcessRequest(method, request_url string, params map[string]string, body []byte, w http.ResponseWriter, r *http.Request) error {

	err := shortlib.IsShortUrl(request_url)
	if err != nil {
		return err
	}

	original_url, err := this.GetOriginalURL(request_url)
	if err != nil {
		return err
	}

	fmt.Printf("REQUEST_URL: %v --- ORIGINAL_URL : %v \n", request_url, original_url)
	http.Redirect(w, r, original_url, http.StatusMovedPermanently)
	return nil
}

func (this *ShortProcessor) GetOriginalURL(request_url string) (string, error) {

	original_url, err := this.Lru.GetOriginalURL(request_url)
	//没有从LRU获取到地址
	if err != nil {
		return "", err
	}

	return original_url, nil

}


================================================
FILE: src/shortlib/Configure.go
================================================
/*************************************************************************
	> File Name: Configure.go
	> Author: Wu Yinghao
	> Mail: wyh817@gmail.com
	> Created Time: 日  6/14 16:00:54 2015
 ************************************************************************/

package shortlib

import (
	"errors"
	"github.com/ewangplay/config"
	"strconv"
)

type Configure struct {
	ConfigureMap map[string]string
}

func NewConfigure(filename string) (*Configure, error) {
	config := &Configure{}

	config.ConfigureMap = make(map[string]string)
	err := config.ParseConfigure(filename)
	if err != nil {
		return nil, err
	}

	return config, nil
}

func (this *Configure) loopConfigure(sectionName string, cfg *config.Config) error {

	if cfg.HasSection(sectionName) {
		section, err := cfg.SectionOptions(sectionName)
		if err == nil {
			for _, v := range section {
				options, err := cfg.String(sectionName, v)
				if err == nil {
					this.ConfigureMap[v] = options
				}
			}

			return nil
		}
		return errors.New("Parse Error")
	}

	return errors.New("No Section")
}

func (this *Configure) ParseConfigure(filename string) error {
	cfg, err := config.ReadDefault(filename)
	if err != nil {
		return err
	}

	this.loopConfigure("server", cfg)
	this.loopConfigure("service", cfg)
	this.loopConfigure("redis", cfg)

	return nil
}

//服务信息
func (this *Configure) GetPort() (int, error) {

	portstr, ok := this.ConfigureMap["port"]
	if ok == false {
		return 9090, errors.New("No Port set, use default")
	}

	port, err := strconv.Atoi(portstr)
	if err != nil {
		return 9090, err
	}

	return port, nil
}

func (this *Configure) GetRedisHost() (string, error) {
	redishost, ok := this.ConfigureMap["redishost"]

	if ok == false {
		return "127.0.0.1", errors.New("No redishost,use defualt")
	}

	return redishost, nil
}

func (this *Configure) GetRedisPort() (string, error) {
	redisport, ok := this.ConfigureMap["redisport"]

	if ok == false {
		return "6379", errors.New("No redisport,use defualt")
	}

	return redisport, nil
}

func (this *Configure) GetRedisStatus() bool {

	status, ok := this.ConfigureMap["status"]
	if ok == false {
		return true
	}

	if status == "true" {
		return true
	}
	return false

}

func (this *Configure) GetHostInfo() string {

	host_name, ok := this.ConfigureMap["hostname"]
	if ok == false {
		return "http://wusay.org/"
	}

	return host_name

}

func (this *Configure) GetCounterType() string {

	count_type, ok := this.ConfigureMap["counter"]
	if ok == false {
		return "inner"
	}

	return count_type

}


================================================
FILE: src/shortlib/LRU.go
================================================
/*************************************************************************
	> File Name: LRU.go
	> Author: Wu Yinghao
	> Mail: wyh817@gmail.com
	> Created Time: 一  6/15 17:07:37 2015
 ************************************************************************/

package shortlib

import (
	"container/list"
	"errors"
	//	"fmt"
)

type UrlElement struct {
	Original string
	Short    string
}

type LRU struct {
	HashShortUrl  map[string]*list.Element
	HashOriginUrl map[string]*list.Element
	ListUrl       *list.List
	RedisCli      *RedisAdaptor
}

func NewLRU(redis_cli *RedisAdaptor) (*LRU, error) {

	lru := &LRU{make(map[string]*list.Element), make(map[string]*list.Element), list.New(), redis_cli}
	return lru, nil
}

func (this *LRU) GetOriginalURL(short_url string) (string, error) {

	element, ok := this.HashShortUrl[short_url]
	//没有找到key,从Redis获取
	if !ok {
		original_url, err := this.RedisCli.GetUrl(short_url)
		//Redis也没有相应的短连接,无法提供服务
		if err != nil {
			return "", errors.New("No URL")
		}
		//更新LRU缓存
		ele := this.ListUrl.PushFront(UrlElement{original_url, short_url})
		this.HashShortUrl[short_url] = ele
		this.HashOriginUrl[original_url] = ele
		return original_url, nil
	}

	//调整位置
	this.ListUrl.MoveToFront(element)
	ele, _ := element.Value.(UrlElement)
	return ele.Original, nil
}

func (this *LRU) GetShortURL(original_url string) (string, error) {

	element, ok := this.HashOriginUrl[original_url]
	//没有找到key,返回错误,重新生成url
	if !ok {
		return "", errors.New("No URL")
	}

	//调整位置
	this.ListUrl.MoveToFront(element)
	ele, _ := element.Value.(UrlElement)
	/*
		fmt.Printf("Short_Url : %v \n",short_url)

		for iter:=this.ListUrl.Front();iter!=nil;iter=iter.Next(){
			fmt.Printf("Element:%v ElementAddr:%v\n",iter.Value,iter)
		}
		fmt.Printf("\n\n\n")
		for key,value := range this.HashUrl{
			fmt.Printf("Key:%v ==== Value:%v\n",key,value)
		}
	*/
	return ele.Short, nil

}

func (this *LRU) SetURL(original_url, short_url string) error {

	ele := this.ListUrl.PushFront(UrlElement{original_url, short_url})
	this.HashShortUrl[short_url] = ele
	this.HashOriginUrl[original_url] = ele
	//将数据存入Redis中
	//fmt.Printf("SET TO REDIS :: short : %v ====> original : %v \n",short_url,original_url)
	err := this.RedisCli.SetUrl(short_url, original_url)
	if err != nil {
		return err
	}
	return nil

}

func (this *LRU) checkList() error {

	return nil
}


================================================
FILE: src/shortlib/LRU_test.go
================================================
/*************************************************************************
	> File Name: LRU_test.go
	> Author: Wu Yinghao
	> Mail: wyh817@gmail.com
	> Created Time: 一  6/15 19:18:06 2015
 ************************************************************************/

package shortlib

import (
	"testing"
)

func Test_SetURL(t *testing.T) {

	lru, _ := NewLRU(nil)
	err := lru.SetURL("key6", "value6")
	err = lru.SetURL("key5", "value5")
	err = lru.SetURL("key4", "value4")
	err = lru.SetURL("key3", "value3")
	err = lru.SetURL("key2", "value2")
	err = lru.SetURL("key1", "value1")
	lru.GetShortURL("key3")
	if err != nil {
		t.Error("Fail....", err)
	} else {
		t.Log("OK...\n")
	}

}


================================================
FILE: src/shortlib/Processor.go
================================================
/*************************************************************************
	> File Name: Processor.go
	> Author: Wu Yinghao
	> Mail: wyh817@gmail.com
	> Created Time: 日  6/14 16:00:54 2015
 ************************************************************************/
package shortlib

import (
	"net/http"
)

type Processor interface {
	/*
	*	基础接口
	*	参数:方法,url参数,请求体
	*	返回:需要返回的http response
	 */
	ProcessRequest(method, request_url string, params map[string]string, body []byte, w http.ResponseWriter, r *http.Request) error
}

type BaseProcessor struct {
	RedisCli      *RedisAdaptor
	Configure     *Configure
	HostName      string
	Lru           *LRU
	CountFunction CreateCountFunc
}


================================================
FILE: src/shortlib/RedisAdaptor.go
================================================
/*************************************************************************
  > File Name: RedisAdaptor.go
  > Author: Wu Yinghao
  > Mail: wyh817@gmail.com
  > Created Time: 二  6/ 9 15:29:05 2015
 ************************************************************************/
package shortlib

import (
	//"errors"
	"fmt"
	"github.com/garyburd/redigo/redis"
)

type RedisAdaptor struct {
	conn   redis.Conn
	config *Configure
}

const SHORT_URL_COUNT_KEY string = "short_url_count"

func NewRedisAdaptor(config *Configure) (*RedisAdaptor, error) {
	redis_cli := &RedisAdaptor{}
	redis_cli.config = config

	host, _ := config.GetRedisHost()
	port, _ := config.GetRedisPort()

	connStr := fmt.Sprintf("%v:%v", host, port)
	fmt.Printf(connStr)
	conn, err := redis.Dial("tcp", connStr)
	if err != nil {
		return nil, err
	}

	redis_cli.conn = conn

	return redis_cli, nil
}

func (this *RedisAdaptor) Release() {
	this.conn.Close()
}

func (this *RedisAdaptor) InitCountService() error {

	_, err := this.conn.Do("SET", SHORT_URL_COUNT_KEY, 0)
	if err != nil {
		return err
	}
	return nil

}

func (this *RedisAdaptor) NewShortUrlCount() (int64, error) {

	count, err := redis.Int64(this.conn.Do("INCR", SHORT_URL_COUNT_KEY))
	if err != nil {
		return 0, err
	}

	return count, nil

}

func (this *RedisAdaptor) SetUrl(short_url, original_url string) error {

	key := fmt.Sprintf("short:%v", short_url)
	_, err := this.conn.Do("SET", key, original_url)
	if err != nil {
		return err
	}
	return nil
}

func (this *RedisAdaptor) GetUrl(short_url string) (string, error) {

	key := fmt.Sprintf("short:%v", short_url)
	original_url, err := redis.String(this.conn.Do("GET", key))
	if err != nil {
		return "", err
	}

	return original_url, nil
}


================================================
FILE: src/shortlib/Router.go
================================================
/*************************************************************************
	> File Name: Router.go
	> Author: Wu Yinghao
	> Mail: wyh817@gmail.com
	> Created Time: 日  6/14 16:00:54 2015
 ************************************************************************/

package shortlib

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

type Router struct {
	Configure  *Configure
	Processors map[int]Processor
}

const (
	SHORT_URL    = 0
	ORIGINAL_URL = 1
	UNKOWN_URL   = 2
)

//路由设置
//数据分发
func (this *Router) ServeHTTP(w http.ResponseWriter, r *http.Request) {

	start := TimeNow()
	request_url := r.RequestURI[1:]
	action, err := this.ParseUrl(request_url)
	if err != nil {
		fmt.Printf("[ERROR]parse url fail : %v \n", err)
	}
	err = r.ParseForm()
	if err != nil {
		return
	}
	params := make(map[string]string)
	for k, v := range r.Form {
		params[k] = v[0]
	}
	body, err := ioutil.ReadAll(r.Body)
	if err != nil && err != io.EOF {
		return
	}

	if r.Method == "GET" {
		action = 0
	} else {
		action = 1
	}

	processor, _ := this.Processors[action]
	err = processor.ProcessRequest(r.Method, request_url, params, body, w, r)
	if err != nil {
		fmt.Printf("[ERROR] : %v\n", err)
	}
	if action == 0 {
		DuringTime(start, "REDIRECT URL ")
	} else {
		DuringTime(start, "CREATE SHORTURL ")
	}
	return
}

func (this *Router) ParseUrl(url string) (action int, err error) {

	if this.isShortUrl(url) {
		return SHORT_URL, nil
	} else {
		return ORIGINAL_URL, nil
	}

}

func (this *Router) isShortUrl(url string) bool {

	short_url_pattern := "XXXX"
	url_reg_exp, err := regexp.Compile(short_url_pattern)
	if err != nil {
		return false
	}
	short_match := url_reg_exp.FindStringSubmatch(url)
	if short_match == nil {
		return false
	}

	return true

}


================================================
FILE: src/shortlib/Utils.go
================================================
/*************************************************************************
	> File Name: Utils.go
	> Author: Wu Yinghao
	> Mail: wyh817@gmail.com
	> Created Time: 日  6/14 18:05:47 2015
 ************************************************************************/

package shortlib

import (
	"container/list"
	"fmt"
	"time"
)

type CountChannl struct {
	Ok           int64
	CountOutChan chan int64
}

type CreateCountFunc func() (int64, error)

func IsAllowToken(token string) bool {
	return true

}

func IsNormalUrl(url string) bool {
	return true
}

func TransNumToString(num int64) (string, error) {

	startTime := TimeNow()
	var base int64
	base = 62
	baseHex := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
	output_list := list.New()
	for num/base != 0 {
		output_list.PushFront(num % base)
		num = num / base
	}
	output_list.PushFront(num % base)
	str := ""
	for iter := output_list.Front(); iter != nil; iter = iter.Next() {
		str = str + string(baseHex[int(iter.Value.(int64))])
	}
	DuringTime(startTime, "TransNumToString")
	return str, nil
}

func TransStringToNum(str string) (int64, error) {

	return 0, nil
}

func TimeNow() time.Time {
	return time.Now()
}

func DuringTime(start time.Time, taskname string) {

	endTime := time.Now()
	fmt.Printf("[INFO] [ %v ] COST Time %v \n", taskname, endTime.Sub(start))

}

func IsShortUrl(short_url string) error {
	return nil
}

func CreateCounter(count_type string, count_chan chan CountChannl, rediscli *RedisAdaptor) CreateCountFunc {

	if count_type == "inner" {
		return func() (int64, error) {
			count_c := make(chan int64)
			ch := CountChannl{0, count_c}
			count_chan <- ch
			count := <-count_c
			return count, nil
		}
	} else {
		return func() (int64, error) {
			count, err := rediscli.NewShortUrlCount()
			if err != nil {
				return 0, err
			}
			return count, nil
		}
	}

}


================================================
FILE: start.sh
================================================
#!/bin/sh

# 在后台启动snsscheduler-server服务
nohup ./bin/ProxyServer &


================================================
FILE: stop.sh
================================================
#!/bin/sh

killall ProxyServer


================================================
FILE: test.sh
================================================
#!/bin/sh

go test ProxyServer
Download .txt
gitextract__l2jne5p/

├── .gitignore
├── README.md
├── config.ini
├── install.sh
├── src/
│   ├── shortService/
│   │   ├── CountThread.go
│   │   ├── OriginalProcessor.go
│   │   ├── Server.go
│   │   └── ShortProcessor.go
│   └── shortlib/
│       ├── Configure.go
│       ├── LRU.go
│       ├── LRU_test.go
│       ├── Processor.go
│       ├── RedisAdaptor.go
│       ├── Router.go
│       └── Utils.go
├── start.sh
├── stop.sh
└── test.sh
Download .txt
SYMBOL INDEX (58 symbols across 11 files)

FILE: src/shortService/CountThread.go
  function CountThread (line 15) | func CountThread(count_chan_in chan shortlib.CountChannl) {

FILE: src/shortService/OriginalProcessor.go
  type OriginalProcessor (line 18) | type OriginalProcessor struct
    method ProcessRequest (line 39) | func (this *OriginalProcessor) ProcessRequest(method, request_url stri...
    method createUrl (line 87) | func (this *OriginalProcessor) createUrl(original_url string) (string,...
    method createResponseJson (line 120) | func (this *OriginalProcessor) createResponseJson(short_url string) (s...
  constant POST (line 23) | POST string = "POST"
  constant TOKEN (line 24) | TOKEN string = "token"
  constant ORIGINAL_URL (line 25) | ORIGINAL_URL string = "original"
  constant SHORT_URL (line 26) | SHORT_URL string = "short"

FILE: src/shortService/Server.go
  function main (line 18) | func main() {

FILE: src/shortService/ShortProcessor.go
  type ShortProcessor (line 16) | type ShortProcessor struct
    method ProcessRequest (line 20) | func (this *ShortProcessor) ProcessRequest(method, request_url string,...
    method GetOriginalURL (line 37) | func (this *ShortProcessor) GetOriginalURL(request_url string) (string...

FILE: src/shortlib/Configure.go
  type Configure (line 16) | type Configure struct
    method loopConfigure (line 32) | func (this *Configure) loopConfigure(sectionName string, cfg *config.C...
    method ParseConfigure (line 52) | func (this *Configure) ParseConfigure(filename string) error {
    method GetPort (line 66) | func (this *Configure) GetPort() (int, error) {
    method GetRedisHost (line 81) | func (this *Configure) GetRedisHost() (string, error) {
    method GetRedisPort (line 91) | func (this *Configure) GetRedisPort() (string, error) {
    method GetRedisStatus (line 101) | func (this *Configure) GetRedisStatus() bool {
    method GetHostInfo (line 115) | func (this *Configure) GetHostInfo() string {
    method GetCounterType (line 126) | func (this *Configure) GetCounterType() string {
  function NewConfigure (line 20) | func NewConfigure(filename string) (*Configure, error) {

FILE: src/shortlib/LRU.go
  type UrlElement (line 16) | type UrlElement struct
  type LRU (line 21) | type LRU struct
    method GetOriginalURL (line 34) | func (this *LRU) GetOriginalURL(short_url string) (string, error) {
    method GetShortURL (line 57) | func (this *LRU) GetShortURL(original_url string) (string, error) {
    method SetURL (line 83) | func (this *LRU) SetURL(original_url, short_url string) error {
    method checkList (line 98) | func (this *LRU) checkList() error {
  function NewLRU (line 28) | func NewLRU(redis_cli *RedisAdaptor) (*LRU, error) {

FILE: src/shortlib/LRU_test.go
  function Test_SetURL (line 14) | func Test_SetURL(t *testing.T) {

FILE: src/shortlib/Processor.go
  type Processor (line 13) | type Processor interface
  type BaseProcessor (line 22) | type BaseProcessor struct

FILE: src/shortlib/RedisAdaptor.go
  type RedisAdaptor (line 15) | type RedisAdaptor struct
    method Release (line 41) | func (this *RedisAdaptor) Release() {
    method InitCountService (line 45) | func (this *RedisAdaptor) InitCountService() error {
    method NewShortUrlCount (line 55) | func (this *RedisAdaptor) NewShortUrlCount() (int64, error) {
    method SetUrl (line 66) | func (this *RedisAdaptor) SetUrl(short_url, original_url string) error {
    method GetUrl (line 76) | func (this *RedisAdaptor) GetUrl(short_url string) (string, error) {
  constant SHORT_URL_COUNT_KEY (line 20) | SHORT_URL_COUNT_KEY string = "short_url_count"
  function NewRedisAdaptor (line 22) | func NewRedisAdaptor(config *Configure) (*RedisAdaptor, error) {

FILE: src/shortlib/Router.go
  type Router (line 18) | type Router struct
    method ServeHTTP (line 31) | func (this *Router) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    method ParseUrl (line 71) | func (this *Router) ParseUrl(url string) (action int, err error) {
    method isShortUrl (line 81) | func (this *Router) isShortUrl(url string) bool {
  constant SHORT_URL (line 24) | SHORT_URL    = 0
  constant ORIGINAL_URL (line 25) | ORIGINAL_URL = 1
  constant UNKOWN_URL (line 26) | UNKOWN_URL   = 2

FILE: src/shortlib/Utils.go
  type CountChannl (line 16) | type CountChannl struct
  type CreateCountFunc (line 21) | type CreateCountFunc
  function IsAllowToken (line 23) | func IsAllowToken(token string) bool {
  function IsNormalUrl (line 28) | func IsNormalUrl(url string) bool {
  function TransNumToString (line 32) | func TransNumToString(num int64) (string, error) {
  function TransStringToNum (line 52) | func TransStringToNum(str string) (int64, error) {
  function TimeNow (line 57) | func TimeNow() time.Time {
  function DuringTime (line 61) | func DuringTime(start time.Time, taskname string) {
  function IsShortUrl (line 68) | func IsShortUrl(short_url string) error {
  function CreateCounter (line 72) | func CreateCounter(count_type string, count_chan chan CountChannl, redis...
Condensed preview — 18 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (24K chars).
[
  {
    "path": ".gitignore",
    "chars": 75,
    "preview": "*.o\n*.swp\n*github.com*\n*bin/\n*pkg/\n*.log*\n*jzlservice/\n.DS_Store\nnohup.out\n"
  },
  {
    "path": "README.md",
    "chars": 1132,
    "preview": "\n## 短链接服务\n\n#### 短连接的原理\n\n很多人一定想的是**短连接是通过一定的算法将长链接变成短连接的,然后访问的时候再还原**,恩,非常高大上,但是仔细想想,怎么可能,那得多牛逼的压缩算法,多长的url都可以压缩为几个字节,而且还"
  },
  {
    "path": "config.ini",
    "chars": 203,
    "preview": "\n[server]\nport = 26719\nhostname = http://t.cn/ #前缀域名\n\n[service]\nthreads = 200\ncounter = redis # inner 使用内部还是Redis进行计数\n\n\n"
  },
  {
    "path": "install.sh",
    "chars": 36,
    "preview": "#!/bin/zsh\n\ngo install shortService\n"
  },
  {
    "path": "src/shortService/CountThread.go",
    "chars": 515,
    "preview": "/*************************************************************************\n\t> File Name: CountThread.go\n\t> Author: Wu Yi"
  },
  {
    "path": "src/shortService/OriginalProcessor.go",
    "chars": 2764,
    "preview": "/*************************************************************************\n\t> File Name: OriginalProcessor.go\n\t> Author:"
  },
  {
    "path": "src/shortService/Server.go",
    "chars": 2060,
    "preview": "/*************************************************************************\n\t> File Name: Server.go\n\t> Author: Wu Yinghao"
  },
  {
    "path": "src/shortService/ShortProcessor.go",
    "chars": 1092,
    "preview": "/*************************************************************************\n\t> File Name: ShortProcessor.go\n\t> Author: Wu"
  },
  {
    "path": "src/shortlib/Configure.go",
    "chars": 2532,
    "preview": "/*************************************************************************\n\t> File Name: Configure.go\n\t> Author: Wu Ying"
  },
  {
    "path": "src/shortlib/LRU.go",
    "chars": 2363,
    "preview": "/*************************************************************************\n\t> File Name: LRU.go\n\t> Author: Wu Yinghao\n\t>"
  },
  {
    "path": "src/shortlib/LRU_test.go",
    "chars": 683,
    "preview": "/*************************************************************************\n\t> File Name: LRU_test.go\n\t> Author: Wu Yingh"
  },
  {
    "path": "src/shortlib/Processor.go",
    "chars": 684,
    "preview": "/*************************************************************************\n\t> File Name: Processor.go\n\t> Author: Wu Ying"
  },
  {
    "path": "src/shortlib/RedisAdaptor.go",
    "chars": 1732,
    "preview": "/*************************************************************************\n  > File Name: RedisAdaptor.go\n  > Author: Wu"
  },
  {
    "path": "src/shortlib/Router.go",
    "chars": 1755,
    "preview": "/*************************************************************************\n\t> File Name: Router.go\n\t> Author: Wu Yinghao"
  },
  {
    "path": "src/shortlib/Utils.go",
    "chars": 1865,
    "preview": "/*************************************************************************\n\t> File Name: Utils.go\n\t> Author: Wu Yinghao\n"
  },
  {
    "path": "start.sh",
    "chars": 66,
    "preview": "#!/bin/sh\n\n# 在后台启动snsscheduler-server服务\nnohup ./bin/ProxyServer &\n"
  },
  {
    "path": "stop.sh",
    "chars": 31,
    "preview": "#!/bin/sh\n\nkillall ProxyServer\n"
  },
  {
    "path": "test.sh",
    "chars": 31,
    "preview": "#!/bin/sh\n\ngo test ProxyServer\n"
  }
]

About this extraction

This page contains the full source code of the wyh267/shortService GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 18 files (19.2 KB), approximately 6.1k tokens, and a symbol index with 58 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!