mirror of
https://github.com/jimeh/ozu.io.git
synced 2026-02-19 08:06:39 +00:00
Refactor shortner and web packages for new Store interface
This commit is contained in:
@@ -1,9 +1,7 @@
|
|||||||
package shortener
|
package shortener
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha1"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/jimeh/go-base58"
|
"github.com/jimeh/go-base58"
|
||||||
"github.com/jimeh/ozu.io/storage"
|
"github.com/jimeh/ozu.io/storage"
|
||||||
@@ -24,55 +22,40 @@ type Base58Shortener struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Shorten a given URL.
|
// Shorten a given URL.
|
||||||
func (s *Base58Shortener) Shorten(rawURL []byte) (uid []byte, url []byte, err error) {
|
func (s *Base58Shortener) Shorten(rawURL []byte) (*storage.Record, error) {
|
||||||
url, err = NormalizeURL(rawURL)
|
url, err := NormalizeURL(rawURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return &storage.Record{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
urlKey := s.makeURLKey(url)
|
record, err := s.Store.FindByURL(url)
|
||||||
uid, err = s.Store.Get(urlKey)
|
if err == nil {
|
||||||
|
return record, nil
|
||||||
if uid != nil && err == nil {
|
} else if err != storage.ErrNotFound {
|
||||||
return uid, url, nil
|
return &storage.Record{}, err
|
||||||
} else if err != nil && err.Error() != "not found" {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uid, err = s.newUID()
|
uid, err := s.newUID()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return &storage.Record{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = s.Store.Set(urlKey, uid)
|
record, err = s.Store.Create(uid, url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return &storage.Record{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
uidKey := s.makeUIDKey(uid)
|
return record, nil
|
||||||
err = s.Store.Set(uidKey, url)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return uid, url, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lookup the URL of a given UID.
|
// Lookup the URL of a given UID.
|
||||||
func (s *Base58Shortener) Lookup(uid []byte) ([]byte, error) {
|
func (s *Base58Shortener) Lookup(uid []byte) (*storage.Record, error) {
|
||||||
_, err := base58.Decode(uid)
|
_, err := base58.Decode(uid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errInvalidUID
|
return &storage.Record{}, errInvalidUID
|
||||||
}
|
}
|
||||||
|
|
||||||
uidKey := s.makeUIDKey(uid)
|
return s.Store.FindByUID(uid)
|
||||||
|
|
||||||
url, err := s.Store.Get(uidKey)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return url, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Base58Shortener) newUID() ([]byte, error) {
|
func (s *Base58Shortener) newUID() ([]byte, error) {
|
||||||
@@ -83,12 +66,3 @@ func (s *Base58Shortener) newUID() ([]byte, error) {
|
|||||||
|
|
||||||
return base58.Encode(index), nil
|
return base58.Encode(index), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Base58Shortener) makeUIDKey(uid []byte) []byte {
|
|
||||||
return append(uidKeyPrefix, uid...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Base58Shortener) makeURLKey(rawURL []byte) []byte {
|
|
||||||
urlSHA := fmt.Sprintf("%x", sha1.Sum(rawURL))
|
|
||||||
return append(urlKeyPrefix, urlSHA...)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
package shortener
|
package shortener
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha1"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jimeh/ozu.io/shortener/mocks"
|
"github.com/jimeh/ozu.io/shortener/mocks"
|
||||||
|
"github.com/jimeh/ozu.io/storage"
|
||||||
"github.com/stretchr/testify/suite"
|
"github.com/stretchr/testify/suite"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -19,52 +18,70 @@ import (
|
|||||||
|
|
||||||
type Base58ShortenerSuite struct {
|
type Base58ShortenerSuite struct {
|
||||||
suite.Suite
|
suite.Suite
|
||||||
store *mocks.Store
|
store *mocks.Store
|
||||||
shortener *Base58Shortener
|
shortener *Base58Shortener
|
||||||
errNotFound error
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Base58ShortenerSuite) SetupTest() {
|
func (s *Base58ShortenerSuite) SetupTest() {
|
||||||
s.store = new(mocks.Store)
|
s.store = new(mocks.Store)
|
||||||
s.shortener = NewBase58(s.store)
|
s.shortener = NewBase58(s.store)
|
||||||
s.errNotFound = errors.New("not found")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests
|
// Tests
|
||||||
|
|
||||||
func (s *Base58ShortenerSuite) TestShortenExisting() {
|
func (s *Base58ShortenerSuite) TestShortenExisting() {
|
||||||
rawURL := []byte("http://google.com/")
|
|
||||||
uid := []byte("ig")
|
uid := []byte("ig")
|
||||||
urlSHA := fmt.Sprintf("%x", sha1.Sum(rawURL))
|
url := []byte("https://google.com/")
|
||||||
|
record := storage.Record{UID: uid, URL: url}
|
||||||
|
|
||||||
s.store.On("Get", append([]byte("url:"), urlSHA...)).Return(uid, nil)
|
s.store.On("FindByURL", url).Return(&record, nil)
|
||||||
|
|
||||||
resultUID, resultURL, err := s.shortener.Shorten(rawURL)
|
result, err := s.shortener.Shorten(url)
|
||||||
s.NoError(err)
|
s.NoError(err)
|
||||||
s.Equal(uid, resultUID)
|
s.Equal(uid, result.UID)
|
||||||
s.Equal(rawURL, resultURL)
|
s.Equal(url, result.URL)
|
||||||
s.store.AssertExpectations(s.T())
|
s.store.AssertExpectations(s.T())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Base58ShortenerSuite) TestShortenNew() {
|
func (s *Base58ShortenerSuite) TestShortenNew() {
|
||||||
rawURL := []byte("https://google.com")
|
|
||||||
url := []byte("https://google.com/")
|
|
||||||
uid := []byte("ig")
|
uid := []byte("ig")
|
||||||
urlKey := append([]byte("url:"), fmt.Sprintf("%x", sha1.Sum(url))...)
|
url := []byte("https://google.com/")
|
||||||
|
record := storage.Record{UID: uid, URL: url}
|
||||||
|
|
||||||
s.store.On("Get", urlKey).Return(nil, s.errNotFound)
|
s.store.On("FindByURL", url).Return(nil, storage.ErrNotFound)
|
||||||
s.store.On("NextSequence").Return(1001, nil)
|
s.store.On("NextSequence").Return(1001, nil)
|
||||||
s.store.On("Set", urlKey, uid).Return(nil)
|
s.store.On("Create", uid, url).Return(&record, nil)
|
||||||
s.store.On("Set", append([]byte("uid:"), uid...), url).Return(nil)
|
|
||||||
|
|
||||||
rUID, rURL, err := s.shortener.Shorten(rawURL)
|
result, err := s.shortener.Shorten(url)
|
||||||
|
|
||||||
s.NoError(err)
|
s.NoError(err)
|
||||||
s.Equal(uid, rUID)
|
s.Equal(uid, result.UID)
|
||||||
s.Equal(url, rURL)
|
s.Equal(url, result.URL)
|
||||||
s.store.AssertExpectations(s.T())
|
s.store.AssertExpectations(s.T())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Base58ShortenerSuite) TestShortenAndNormalizeURL() {
|
||||||
|
examples := []struct {
|
||||||
|
url []byte
|
||||||
|
normalized []byte
|
||||||
|
}{
|
||||||
|
{[]byte("google.com"), []byte("http://google.com/")},
|
||||||
|
{[]byte("google.com/"), []byte("http://google.com/")},
|
||||||
|
{[]byte("http://google.com"), []byte("http://google.com/")},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, e := range examples {
|
||||||
|
record := storage.Record{UID: []byte("ig"), URL: e.normalized}
|
||||||
|
s.store.On("FindByURL", record.URL).Return(&record, nil)
|
||||||
|
|
||||||
|
result, err := s.shortener.Shorten(e.url)
|
||||||
|
s.NoError(err)
|
||||||
|
s.Equal(record.UID, result.UID)
|
||||||
|
s.Equal(record.URL, result.URL)
|
||||||
|
s.store.AssertExpectations(s.T())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Base58ShortenerSuite) TestShortenInvalidURL() {
|
func (s *Base58ShortenerSuite) TestShortenInvalidURL() {
|
||||||
examples := []struct {
|
examples := []struct {
|
||||||
url string
|
url string
|
||||||
@@ -93,9 +110,9 @@ func (s *Base58ShortenerSuite) TestShortenInvalidURL() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, e := range examples {
|
for _, e := range examples {
|
||||||
rUID, rURL, err := s.shortener.Shorten([]byte(e.url))
|
record, err := s.shortener.Shorten([]byte(e.url))
|
||||||
s.Nil(rUID)
|
s.Nil(record.UID)
|
||||||
s.Nil(rURL)
|
s.Nil(record.URL)
|
||||||
s.EqualError(err, e.error)
|
s.EqualError(err, e.error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -103,48 +120,50 @@ func (s *Base58ShortenerSuite) TestShortenInvalidURL() {
|
|||||||
func (s *Base58ShortenerSuite) TestShortenStoreError() {
|
func (s *Base58ShortenerSuite) TestShortenStoreError() {
|
||||||
url := []byte("https://google.com/")
|
url := []byte("https://google.com/")
|
||||||
storeErr := errors.New("leveldb: something wrong")
|
storeErr := errors.New("leveldb: something wrong")
|
||||||
urlKey := append([]byte("url:"), fmt.Sprintf("%x", sha1.Sum(url))...)
|
|
||||||
|
|
||||||
s.store.On("Get", urlKey).Return(nil, storeErr)
|
s.store.On("FindByURL", url).Return(nil, storeErr)
|
||||||
|
|
||||||
rUID, rURL, err := s.shortener.Shorten(url)
|
result, err := s.shortener.Shorten(url)
|
||||||
s.Nil(rUID)
|
s.Nil(result.UID)
|
||||||
s.Nil(rURL)
|
s.Nil(result.URL)
|
||||||
s.EqualError(err, storeErr.Error())
|
s.EqualError(err, storeErr.Error())
|
||||||
|
s.store.AssertExpectations(s.T())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Base58ShortenerSuite) TestLookupExisting() {
|
func (s *Base58ShortenerSuite) TestLookupExisting() {
|
||||||
url := []byte("https://google.com/")
|
|
||||||
uid := []byte("ig")
|
uid := []byte("ig")
|
||||||
|
url := []byte("https://google.com/")
|
||||||
|
record := storage.Record{UID: uid, URL: url}
|
||||||
|
|
||||||
s.store.On("Get", append([]byte("uid:"), uid...)).Return(url, nil)
|
s.store.On("FindByUID", uid).Return(&record, nil)
|
||||||
|
|
||||||
rURL, err := s.shortener.Lookup(uid)
|
|
||||||
|
|
||||||
|
result, err := s.shortener.Lookup(uid)
|
||||||
s.NoError(err)
|
s.NoError(err)
|
||||||
s.Equal(url, rURL)
|
s.Equal(uid, result.UID)
|
||||||
|
s.Equal(url, result.URL)
|
||||||
s.store.AssertExpectations(s.T())
|
s.store.AssertExpectations(s.T())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Base58ShortenerSuite) TestLookupNonExistant() {
|
func (s *Base58ShortenerSuite) TestLookupNonExistant() {
|
||||||
uid := []byte("ig")
|
uid := []byte("ig")
|
||||||
|
|
||||||
s.store.On("Get", append([]byte("uid:"), uid...)).Return(nil, s.errNotFound)
|
s.store.On("FindByUID", uid).Return(&storage.Record{}, storage.ErrNotFound)
|
||||||
|
|
||||||
rURL, err := s.shortener.Lookup(uid)
|
|
||||||
|
|
||||||
|
result, err := s.shortener.Lookup(uid)
|
||||||
s.EqualError(err, "not found")
|
s.EqualError(err, "not found")
|
||||||
s.Nil(rURL)
|
s.Nil(result.UID)
|
||||||
|
s.Nil(result.URL)
|
||||||
s.store.AssertExpectations(s.T())
|
s.store.AssertExpectations(s.T())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Base58ShortenerSuite) TestLookupInvalid() {
|
func (s *Base58ShortenerSuite) TestLookupInvalid() {
|
||||||
uid := []byte("ig\"; drop table haha")
|
uid := []byte("ig\"; drop table haha")
|
||||||
|
|
||||||
rURL, err := s.shortener.Lookup(uid)
|
result, err := s.shortener.Lookup(uid)
|
||||||
|
|
||||||
s.EqualError(err, "invalid UID")
|
s.EqualError(err, "invalid UID")
|
||||||
s.Nil(rURL)
|
s.Nil(result.UID)
|
||||||
|
s.Nil(result.URL)
|
||||||
s.store.AssertExpectations(s.T())
|
s.store.AssertExpectations(s.T())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,36 +22,114 @@ func (_m *Store) Close() error {
|
|||||||
return r0
|
return r0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete provides a mock function with given fields: _a0
|
// Create provides a mock function with given fields: UID, URL
|
||||||
func (_m *Store) Delete(_a0 []byte) error {
|
func (_m *Store) Create(UID []byte, URL []byte) (*storage.Record, error) {
|
||||||
ret := _m.Called(_a0)
|
ret := _m.Called(UID, URL)
|
||||||
|
|
||||||
var r0 error
|
var r0 *storage.Record
|
||||||
if rf, ok := ret.Get(0).(func([]byte) error); ok {
|
if rf, ok := ret.Get(0).(func([]byte, []byte) *storage.Record); ok {
|
||||||
r0 = rf(_a0)
|
r0 = rf(UID, URL)
|
||||||
} else {
|
|
||||||
r0 = ret.Error(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
return r0
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get provides a mock function with given fields: _a0
|
|
||||||
func (_m *Store) Get(_a0 []byte) ([]byte, error) {
|
|
||||||
ret := _m.Called(_a0)
|
|
||||||
|
|
||||||
var r0 []byte
|
|
||||||
if rf, ok := ret.Get(0).(func([]byte) []byte); ok {
|
|
||||||
r0 = rf(_a0)
|
|
||||||
} else {
|
} else {
|
||||||
if ret.Get(0) != nil {
|
if ret.Get(0) != nil {
|
||||||
r0 = ret.Get(0).([]byte)
|
r0 = ret.Get(0).(*storage.Record)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func([]byte, []byte) error); ok {
|
||||||
|
r1 = rf(UID, URL)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteByUID provides a mock function with given fields: UID
|
||||||
|
func (_m *Store) DeleteByUID(UID []byte) (*storage.Record, error) {
|
||||||
|
ret := _m.Called(UID)
|
||||||
|
|
||||||
|
var r0 *storage.Record
|
||||||
|
if rf, ok := ret.Get(0).(func([]byte) *storage.Record); ok {
|
||||||
|
r0 = rf(UID)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*storage.Record)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var r1 error
|
var r1 error
|
||||||
if rf, ok := ret.Get(1).(func([]byte) error); ok {
|
if rf, ok := ret.Get(1).(func([]byte) error); ok {
|
||||||
r1 = rf(_a0)
|
r1 = rf(UID)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteByURL provides a mock function with given fields: URL
|
||||||
|
func (_m *Store) DeleteByURL(URL []byte) (*storage.Record, error) {
|
||||||
|
ret := _m.Called(URL)
|
||||||
|
|
||||||
|
var r0 *storage.Record
|
||||||
|
if rf, ok := ret.Get(0).(func([]byte) *storage.Record); ok {
|
||||||
|
r0 = rf(URL)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*storage.Record)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func([]byte) error); ok {
|
||||||
|
r1 = rf(URL)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindByUID provides a mock function with given fields: UID
|
||||||
|
func (_m *Store) FindByUID(UID []byte) (*storage.Record, error) {
|
||||||
|
ret := _m.Called(UID)
|
||||||
|
|
||||||
|
var r0 *storage.Record
|
||||||
|
if rf, ok := ret.Get(0).(func([]byte) *storage.Record); ok {
|
||||||
|
r0 = rf(UID)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*storage.Record)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func([]byte) error); ok {
|
||||||
|
r1 = rf(UID)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindByURL provides a mock function with given fields: URL
|
||||||
|
func (_m *Store) FindByURL(URL []byte) (*storage.Record, error) {
|
||||||
|
ret := _m.Called(URL)
|
||||||
|
|
||||||
|
var r0 *storage.Record
|
||||||
|
if rf, ok := ret.Get(0).(func([]byte) *storage.Record); ok {
|
||||||
|
r0 = rf(URL)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*storage.Record)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func([]byte) error); ok {
|
||||||
|
r1 = rf(URL)
|
||||||
} else {
|
} else {
|
||||||
r1 = ret.Error(1)
|
r1 = ret.Error(1)
|
||||||
}
|
}
|
||||||
@@ -80,18 +158,4 @@ func (_m *Store) NextSequence() (int, error) {
|
|||||||
return r0, r1
|
return r0, r1
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set provides a mock function with given fields: _a0, _a1
|
|
||||||
func (_m *Store) Set(_a0 []byte, _a1 []byte) error {
|
|
||||||
ret := _m.Called(_a0, _a1)
|
|
||||||
|
|
||||||
var r0 error
|
|
||||||
if rf, ok := ret.Get(0).(func([]byte, []byte) error); ok {
|
|
||||||
r0 = rf(_a0, _a1)
|
|
||||||
} else {
|
|
||||||
r0 = ret.Error(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
return r0
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ storage.Store = (*Store)(nil)
|
var _ storage.Store = (*Store)(nil)
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
package shortener
|
package shortener
|
||||||
|
|
||||||
|
import "github.com/jimeh/ozu.io/storage"
|
||||||
|
|
||||||
// Shortener defines a shortener interface for shortening URLs.
|
// Shortener defines a shortener interface for shortening URLs.
|
||||||
type Shortener interface {
|
type Shortener interface {
|
||||||
Shorten([]byte) ([]byte, []byte, error)
|
Shorten([]byte) (*storage.Record, error)
|
||||||
Lookup([]byte) ([]byte, error)
|
Lookup([]byte) (*storage.Record, error)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,24 +20,24 @@ type APIHandler struct {
|
|||||||
|
|
||||||
// Shorten shortens given URL.
|
// Shorten shortens given URL.
|
||||||
func (h *APIHandler) Shorten(c *routing.Context) error {
|
func (h *APIHandler) Shorten(c *routing.Context) error {
|
||||||
uid, url, err := h.shortener.Shorten(c.FormValue("url"))
|
record, err := h.shortener.Shorten(c.FormValue("url"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return h.respondWithError(c, err)
|
return h.respondWithError(c, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
r := makeResponse(c, uid, url)
|
r := makeResponse(c, record)
|
||||||
return h.respond(c, &r)
|
return h.respond(c, &r)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lookup shortened UID.
|
// Lookup shortened UID.
|
||||||
func (h *APIHandler) Lookup(c *routing.Context) error {
|
func (h *APIHandler) Lookup(c *routing.Context) error {
|
||||||
uid := c.FormValue("uid")
|
uid := c.FormValue("uid")
|
||||||
url, err := h.shortener.Lookup(uid)
|
record, err := h.shortener.Lookup(uid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return h.respondWithError(c, err)
|
return h.respondWithError(c, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
r := makeResponse(c, uid, url)
|
r := makeResponse(c, record)
|
||||||
return h.respond(c, &r)
|
return h.respond(c, &r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -71,12 +71,12 @@ func (h *Handler) Index(c *routing.Context) error {
|
|||||||
rawURL := c.FormValue("url")
|
rawURL := c.FormValue("url")
|
||||||
|
|
||||||
if len(rawURL) > 0 {
|
if len(rawURL) > 0 {
|
||||||
uid, url, err := h.shortener.Shorten(rawURL)
|
record, err := h.shortener.Shorten(rawURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return h.respond(c, template, makeErrResponse(err))
|
return h.respond(c, template, makeErrResponse(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
r := makeResponse(c, uid, url)
|
r := makeResponse(c, record)
|
||||||
return h.respond(c, template, r)
|
return h.respond(c, template, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,19 +106,19 @@ func (h *Handler) Static(c *routing.Context) error {
|
|||||||
func (h *Handler) LookupAndRedirect(c *routing.Context) error {
|
func (h *Handler) LookupAndRedirect(c *routing.Context) error {
|
||||||
uid := []byte(c.Param("uid"))
|
uid := []byte(c.Param("uid"))
|
||||||
|
|
||||||
url, err := h.shortener.Lookup(uid)
|
record, err := h.shortener.Lookup(uid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return h.NotFound(c)
|
return h.NotFound(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
r := makeResponse(c, uid, url)
|
r := makeResponse(c, record)
|
||||||
|
|
||||||
c.Response.Header.Set("Pragma", "no-cache")
|
c.Response.Header.Set("Pragma", "no-cache")
|
||||||
c.Response.Header.Set("Expires", "Mon, 01 Jan 1990 00:00:00 GMT")
|
c.Response.Header.Set("Expires", "Mon, 01 Jan 1990 00:00:00 GMT")
|
||||||
c.Response.Header.Set("X-XSS-Protection", "1; mode=block")
|
c.Response.Header.Set("X-XSS-Protection", "1; mode=block")
|
||||||
c.Response.Header.Set("Cache-Control",
|
c.Response.Header.Set("Cache-Control",
|
||||||
"no-cache, no-store, max-age=0, must-revalidate")
|
"no-cache, no-store, max-age=0, must-revalidate")
|
||||||
c.Redirect(string(url), fasthttp.StatusMovedPermanently)
|
c.Redirect(string(record.URL), fasthttp.StatusMovedPermanently)
|
||||||
c.Response.Header.Set("Connection", "close")
|
c.Response.Header.Set("Connection", "close")
|
||||||
c.Response.Header.Set("X-Content-Type-Options", "nosniff")
|
c.Response.Header.Set("X-Content-Type-Options", "nosniff")
|
||||||
c.Response.Header.Set("Accept-Ranges", "none")
|
c.Response.Header.Set("Accept-Ranges", "none")
|
||||||
|
|||||||
@@ -3,14 +3,15 @@ package web
|
|||||||
import (
|
import (
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
|
"github.com/jimeh/ozu.io/storage"
|
||||||
"github.com/qiangxue/fasthttp-routing"
|
"github.com/qiangxue/fasthttp-routing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func makeResponse(c *routing.Context, uid []byte, url []byte) Response {
|
func makeResponse(c *routing.Context, r *storage.Record) Response {
|
||||||
return Response{
|
return Response{
|
||||||
UID: string(uid),
|
UID: string(r.UID),
|
||||||
URL: makeShortURL(c, uid),
|
URL: makeShortURL(c, r.UID),
|
||||||
Target: string(url),
|
Target: string(r.URL),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user