program story

URL 단축기를 어떻게 만듭니 까?

inputbox 2020. 10. 2. 22:12
반응형

URL 단축기를 어떻게 만듭니 까?


긴 URL을 입력 필드에 쓸 수 있고 서비스가 URL을 " http://www.example.org/abcdef"로 단축 할 수있는 URL 단축 서비스를 만들고 싶습니다 .

" abcdef" 대신을 포함하는 6 개의 문자가있는 다른 문자열이있을 수 있습니다 a-z, A-Z and 0-9. 이는 560 ~ 570 억 개의 현을 가능하게합니다.

내 접근 방식 :

세 개의 열이있는 데이터베이스 테이블이 있습니다.

  1. ID, 정수, 자동 증가
  2. long, string, 사용자가 입력 한 긴 URL
  3. short, string, 단축 URL (또는 6 자)

그런 다음 긴 URL을 테이블에 삽입합니다. 그런 다음 " id"에 대한 자동 증가 값을 선택하고 해시를 작성합니다. 이 해시는 " short" 로 삽입되어야합니다 . 하지만 어떤 종류의 해시를 만들어야합니까? MD5와 같은 해시 알고리즘은 너무 긴 문자열을 만듭니다. 이 알고리즘을 사용하지 않는 것 같습니다. 자체 구축 된 알고리즘도 작동합니다.

내 생각:

" http://www.google.de/"의 경우 자동 증가 ID를 얻습니다 239472. 그런 다음 다음 단계를 수행합니다.

short = '';
if divisible by 2, add "a"+the result to short
if divisible by 3, add "b"+the result to short
... until I have divisors for a-z and A-Z.

숫자가 더 이상 나눌 수 없을 때까지 반복 될 수 있습니다. 이것이 좋은 접근법이라고 생각하십니까? 더 좋은 아이디어가 있습니까?

이 주제에 대한 지속적인 관심으로 인해 JavaScript , PHP , PythonJava 구현 이 포함 된 효율적인 GitHub 솔루션을 게시했습니다 . 원하는 경우 솔루션 추가 :)


나는 당신의 "숫자를 문자열로 변환"접근법을 계속할 것입니다. 그러나 ID가 소수이고 52보다 크면 제안 된 알고리즘이 실패한다는 것을 알게됩니다 .

이론적 배경

Bijective 함수 가 필요합니다 f . 이는 f (123) = 'abc' 함수에 대해 역함수 g ( 'abc') = 123찾을 수 있도록하기 위해 필요 합니다. 이것은 다음을 의미합니다.

  • f (x1) = f (x2)를 만드는 x1, x2 (x1 ≠ x2 포함) 가 없어야합니다 .
  • 그리고 모든 y에 대해 f (x) = y가 되도록 x 를 찾을 수 있어야합니다 .

ID를 단축 URL로 변환하는 방법

  1. 우리가 사용하고 싶은 알파벳을 생각해보십시오. 귀하의 경우에는 [a-zA-Z0-9]. 62 개의 문자 가 포함되어 있습니다 .
  2. 자동 생성 된 고유 한 숫자 키 ( id예 : MySQL 테이블 의 자동 증가) 가져옵니다 .

    이 예에서는 125 10 (10을 밑으로하는 125)을 사용합니다.

  3. 이제 125 10 을 X 62 (기본 62) 로 변환해야합니다 .

    125 (10) = 2 × 62 1 + 1 × 62 0 =[2,1]

    이를 위해서는 정수 나눗셈과 모듈로를 사용해야합니다. 의사 코드 예 :

    digits = []
    
    while num > 0
      remainder = modulo(num, 62)
      digits.push(remainder)
      num = divide(num, 62)
    
    digits = digits.reverse
    

    이제 인덱스 2와 1 을 알파벳에 매핑하십시오 . 다음은 매핑 (예 : 배열 사용)이 다음과 같은 모습입니다.

    0  → a
    1  → b
    ...
    25 → z
    ...
    52 → 0
    61 → 9
    

    2 → c 및 1 → b를 사용하면 단축 URL로 cb 62받게됩니다 .

    http://shor.ty/cb
    

단축 된 URL을 초기 ID로 확인하는 방법

그 반대는 더 쉽습니다. 알파벳에서 역방향 조회를 수행합니다.

  1. e9a 62 는 "알파벳의 4 번째, 61 번째, 0 번째 문자"로 해석됩니다.

    e9a 62 = [4,61,0]= 4 × 62 2 + 61 62 × 1 + 0 × 62 0 = 19,158 10

  2. 이제 데이터베이스 레코드를 찾고 WHERE id = 19158리디렉션을 수행하십시오.

구현 예 (코멘트 작성자가 제공)


해시를 사용하는 이유는 무엇입니까?

자동 증가 값을 영숫자 값으로 간단하게 변환 할 수 있습니다. 기본 변환을 사용하여 쉽게 할 수 있습니다. 문자 공간 (AZ, az, 0-9 등)이 40 자이고 ID를 40 진법 숫자로 변환하고 문자를 숫자로 사용한다고 가정합니다.


public class UrlShortener {
    private static final String ALPHABET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    private static final int    BASE     = ALPHABET.length();

    public static String encode(int num) {
        StringBuilder sb = new StringBuilder();
        while ( num > 0 ) {
            sb.append( ALPHABET.charAt( num % BASE ) );
            num /= BASE;
        }
        return sb.reverse().toString();   
    }

    public static int decode(String str) {
        int num = 0;
        for ( int i = 0; i < str.length(); i++ )
            num = num * BASE + ALPHABET.indexOf(str.charAt(i));
        return num;
    }   
}

귀하의 질문에 대한 답변은 아니지만 대소 문자를 구분하는 단축 URL을 사용하지 않습니다. 그들은 기억하기 어렵고 일반적으로 읽을 수 없으며 (많은 글꼴이 1과 l, 0과 O 및 다른 문자를 매우 유사하게 렌더링하여 차이를 구분할 수 없음) 완전히 오류가 발생하기 쉽습니다. 소문자 또는 대문자 만 사용하십시오.

또한 미리 정의 된 형식으로 숫자와 문자를 혼합하는 형식을 사용하십시오. 사람들이 한 형식을 다른 형식보다 더 잘 기억하는 경향이 있다는 연구 결과가 있습니다 (번호가 특정 형식으로 그룹화되어있는 전화 번호를 생각해보세요). num-char-char-num-char-char과 같은 것을 시도하십시오. 나는 이것이 특히 대문자와 소문자가없는 경우 조합을 낮출 것이라는 것을 알고 있지만 더 유용하고 유용 할 것입니다.


내 접근 방식 : 데이터베이스 ID를 가져온 다음 Base36 인코딩합니다 . 대문자와 소문자를 모두 사용하지 않을 것입니다. 전화를 통해 URL을 전송하는 것이 악몽이되기 때문입니다.하지만 당연히이 기능을 기본 62 인코더 / 디코더로 쉽게 확장 할 수 있습니다.


여기 내 PHP 5 수업이 있습니다.

<?php
class Bijective
{
    public $dictionary = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

    public function __construct()
    {
        $this->dictionary = str_split($this->dictionary);
    }

    public function encode($i)
    {
        if ($i == 0)
        return $this->dictionary[0];

        $result = '';
        $base = count($this->dictionary);

        while ($i > 0)
        {
            $result[] = $this->dictionary[($i % $base)];
            $i = floor($i / $base);
        }

        $result = array_reverse($result);

        return join("", $result);
    }

    public function decode($input)
    {
        $i = 0;
        $base = count($this->dictionary);

        $input = str_split($input);

        foreach($input as $char)
        {
            $pos = array_search($char, $this->dictionary);

            $i = $i * $base + $pos;
        }

        return $i;
    }
}

Node.js 및 MongoDB 솔루션

MongoDB가 12 바이트의 새 ObjectId를 만드는 데 사용하는 형식을 알고 있기 때문입니다.

  • Unix 시대 이후 초를 나타내는 4 바이트 값
  • 3 바이트 기계 식별자,
  • 2 바이트 프로세스 ID
  • 임의의 값으로 시작하는 3 바이트 카운터 (컴퓨터에서)

예 (무작위 시퀀스 선택) a1b2c3d4e5f6g7h8i9j1k2l3

  • a1b2c3d4는 Unix 시대 이후의 초를 나타냅니다.
  • 4e5f6g7은 기계 식별자를 나타냅니다.
  • h8i9는 프로세스 ID를 나타냅니다.
  • j1k2l3은 임의의 값으로 시작하는 카운터를 나타냅니다.

동일한 시스템에 데이터를 저장하면 카운터가 고유하므로 중복 될 것이라는 의심없이 가져올 수 있습니다.

따라서 짧은 URL이 카운터가 되고 여기에 서버가 제대로 실행되고 있다고 가정하는 코드 스 니펫이 있습니다.

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

// Create a schema
const shortUrl = new Schema({
    long_url: { type: String, required: true },
    short_url: { type: String, required: true, unique: true },
  });
const ShortUrl = mongoose.model('ShortUrl', shortUrl);

// The user can request to get a short URL by providing a long URL using a form

app.post('/shorten', function(req ,res){
    // Create a new shortUrl */
    // The submit form has an input with longURL as its name attribute.
    const longUrl = req.body["longURL"];
    const newUrl = ShortUrl({
        long_url : longUrl,
        short_url : "",
    });
    const shortUrl = newUrl._id.toString().slice(-6);
    newUrl.short_url = shortUrl;
    console.log(newUrl);
    newUrl.save(function(err){
        console.log("the new URL is added");
    })
});

C # 버전 :

public class UrlShortener 
{
    private static String ALPHABET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    private static int    BASE     = 62;

    public static String encode(int num)
    {
        StringBuilder sb = new StringBuilder();

        while ( num > 0 )
        {
            sb.Append( ALPHABET[( num % BASE )] );
            num /= BASE;
        }

        StringBuilder builder = new StringBuilder();
        for (int i = sb.Length - 1; i >= 0; i--)
        {
            builder.Append(sb[i]);
        }
        return builder.ToString(); 
    }

    public static int decode(String str)
    {
        int num = 0;

        for ( int i = 0, len = str.Length; i < len; i++ )
        {
            num = num * BASE + ALPHABET.IndexOf( str[(i)] ); 
        }

        return num;
    }   
}

전체 URL을 해시 할 수 있지만 ID를 줄이려면 marcel가 제안한대로 수행하십시오. 이 Python 구현을 작성했습니다.

https://gist.github.com/778542


당신이 바퀴를 재발 명하고 싶지 않다면… http://lilurl.sourceforge.net/


// simple approach

$original_id = 56789;

$shortened_id = base_convert($original_id, 10, 36);

$un_shortened_id = base_convert($shortened_id, 36, 10);

데이터베이스의 도메인 당 정수 시퀀스를 계속 증가시키고 Hashids 를 사용하여 정수를 URL 경로로 인코딩합니다.

static hashids = Hashids(salt = "my app rocks", minSize = 6)

문자 길이가 다 소모 될 때까지 걸리는 시간을 확인하기 위해 스크립트를 실행했습니다. 6 개의 문자의 경우 164,916,224링크를 수행 한 다음 최대 7 개의 문자로 이동합니다. Bitly는 7 개의 문자를 사용합니다. 5 자 미만이 이상해 보입니다.

Hashids 는 URL 경로를 다시 정수로 디코딩 할 수 있지만 더 간단한 해결책은 전체 짧은 링크 sho.rt/ka8ds3를 기본 키로 사용하는 것입니다.

전체 개념은 다음과 같습니다.

function addDomain(domain) {
    table("domains").insert("domain", domain, "seq", 0)
}

function addURL(domain, longURL) {
    seq = table("domains").where("domain = ?", domain).increment("seq")
    shortURL = domain + "/" + hashids.encode(seq)
    table("links").insert("short", shortURL, "long", longURL)
    return shortURL
}

// GET /:hashcode
function handleRequest(req, res) {
    shortURL = req.host + "/" + req.param("hashcode")
    longURL = table("links").where("short = ?", shortURL).get("long")
    res.redirect(301, longURL)
}

alphabet = map(chr, range(97,123)+range(65,91)) + map(str,range(0,10))

def lookup(k, a=alphabet):
    if type(k) == int:
        return a[k]
    elif type(k) == str:
        return a.index(k)


def encode(i, a=alphabet):
    '''Takes an integer and returns it in the given base with mappings for upper/lower case letters and numbers 0-9.'''
    try:
        i = int(i)
    except Exception:
        raise TypeError("Input must be an integer.")

    def incode(i=i, p=1, a=a):
        # Here to protect p.                                                                                                                                                                                                                
        if i <= 61:
            return lookup(i)

        else:
            pval = pow(62,p)
            nval = i/pval
            remainder = i % pval
            if nval <= 61:
                return lookup(nval) + incode(i % pval)
            else:
                return incode(i, p+1)

    return incode()



def decode(s, a=alphabet):
    '''Takes a base 62 string in our alphabet and returns it in base10.'''
    try:
        s = str(s)
    except Exception:
        raise TypeError("Input must be a string.")

    return sum([lookup(i) * pow(62,p) for p,i in enumerate(list(reversed(s)))])a

필요한 사람을위한 내 버전이 있습니다.


다음은 PHP를위한 적절한 URL 인코딩 기능입니다.

// From http://snipplr.com/view/22246/base62-encode--decode/
private function base_encode($val, $base=62, $chars='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') {
    $str = '';
    do {
        $i = fmod($val, $base);
        $str = $chars[$i] . $str;
        $val = ($val - $i) / $base;
    } while($val > 0);
    return $str;
}

누군가 이것이 유용하다고 생각할지 모르겠습니다. 'hack n slash'방법에 가깝지만 특정 문자 만 원하는 경우 간단하고 잘 작동합니다.

$dictionary = "abcdfghjklmnpqrstvwxyz23456789";
$dictionary = str_split($dictionary);

// Encode
$str_id = '';
$base = count($dictionary);

while($id > 0) {
    $rem = $id % $base;
    $id = ($id - $rem) / $base;
    $str_id .= $dictionary[$rem];
}


// Decode
$id_ar = str_split($str_id);
$id = 0;

for($i = count($id_ar); $i > 0; $i--) {
    $id += array_search($id_ar[$i-1], $dictionary) * pow($base, $i - 1);
} 

일부러 O, 0, i를 생략 했습니까?

방금 Ryan의 솔루션을 기반으로 PHP 클래스를 만들었습니다.

<?php

    $shorty = new App_Shorty();

    echo 'ID: ' . 1000;
    echo '<br/> Short link: ' . $shorty->encode(1000);
    echo '<br/> Decoded Short Link: ' . $shorty->decode($shorty->encode(1000));


    /**
     * A nice shorting class based on Ryan Charmley's suggestion see the link on Stack Overflow below.
     * @author Svetoslav Marinov (Slavi) | http://WebWeb.ca
     * @see http://stackoverflow.com/questions/742013/how-to-code-a-url-shortener/10386945#10386945
     */
    class App_Shorty {
        /**
         * Explicitly omitted: i, o, 1, 0 because they are confusing. Also use only lowercase ... as
         * dictating this over the phone might be tough.
         * @var string
         */
        private $dictionary = "abcdfghjklmnpqrstvwxyz23456789";
        private $dictionary_array = array();

        public function __construct() {
            $this->dictionary_array = str_split($this->dictionary);
        }

        /**
         * Gets ID and converts it into a string.
         * @param int $id
         */
        public function encode($id) {
            $str_id = '';
            $base = count($this->dictionary_array);

            while ($id > 0) {
                $rem = $id % $base;
                $id = ($id - $rem) / $base;
                $str_id .= $this->dictionary_array[$rem];
            }

            return $str_id;
        }

        /**
         * Converts /abc into an integer ID
         * @param string
         * @return int $id
         */
        public function decode($str_id) {
            $id = 0;
            $id_ar = str_split($str_id);
            $base = count($this->dictionary_array);

            for ($i = count($id_ar); $i > 0; $i--) {
                $id += array_search($id_ar[$i - 1], $this->dictionary_array) * pow($base, $i - 1);
            }
            return $id;
        }
    }
?>

ID를 문자열로 변환하지 않는 이유는 무엇입니까? 0과 61 사이의 숫자를 단일 문자 (대 / 소문자) 또는 숫자로 매핑하는 함수 만 있으면됩니다. 그런 다음이를 적용하여 예를 들어 4 글자 코드를 생성하면 1470 만 개의 URL이 포함됩니다.


이것이 내가 사용하는 것입니다.

# Generate a [0-9a-zA-Z] string
ALPHABET = map(str,range(0, 10)) + map(chr, range(97, 123) + range(65, 91))

def encode_id(id_number, alphabet=ALPHABET):
    """Convert an integer to a string."""
    if id_number == 0:
        return alphabet[0]

    alphabet_len = len(alphabet) # Cache

    result = ''
    while id_number > 0:
        id_number, mod = divmod(id_number, alphabet_len)
        result = alphabet[mod] + result

    return result

def decode_id(id_string, alphabet=ALPHABET):
    """Convert a string to an integer."""
    alphabet_len = len(alphabet) # Cache
    return sum([alphabet.index(char) * pow(alphabet_len, power) for power, char in enumerate(reversed(id_string))])

매우 빠르고 긴 정수를 취할 수 있습니다.


비슷한 프로젝트의 경우 새 키를 얻기 위해 해시 테이블에서 아직 사용되지 않은 문자열을 얻을 때까지 생성기 를 호출 하는 임의 문자열 생성기 주위에 래퍼 함수를 ​​만듭니다 . 이 방법은 네임 스페이스가 가득 차기 시작하면 속도가 느려지지만 앞서 말했듯이 6 자만으로도 작업 할 네임 스페이스가 충분합니다.


여러 작성자의 웹 페이지를 저장하고 추측에 의한 페이지 검색을 방지해야한다는 점에서 문제의 변형이 있습니다. 따라서 내 짧은 URL은 페이지 번호의 Base-62 문자열에 몇 개의 추가 숫자를 추가합니다. 이러한 추가 숫자는 페이지 레코드 자체의 정보에서 생성되며 3844 URL 중 1 개만 유효한지 확인합니다 (2 자리 Base-62 가정). http://mgscan.com/MBWL 에서 개요 설명을 볼 수 있습니다 .


아주 좋은 대답입니다. bjf의 Golang 구현을 만들었습니다.

package bjf

import (
    "math"
    "strings"
    "strconv"
)

const alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"

func Encode(num string) string {
    n, _ := strconv.ParseUint(num, 10, 64)
    t := make([]byte, 0)

    /* Special case */
    if n == 0 {
        return string(alphabet[0])
    }

    /* Map */
    for n > 0 {
        r := n % uint64(len(alphabet))
        t = append(t, alphabet[r])
        n = n / uint64(len(alphabet))
    }

    /* Reverse */
    for i, j := 0, len(t) - 1; i < j; i, j = i + 1, j - 1 {
        t[i], t[j] = t[j], t[i]
    }

    return string(t)
}

func Decode(token string) int {
    r := int(0)
    p := float64(len(token)) - 1

    for i := 0; i < len(token); i++ {
        r += strings.Index(alphabet, string(token[i])) * int(math.Pow(float64(len(alphabet)), p))
        p--
    }

    return r
}

github에서 호스팅 : https://github.com/xor-gate/go-bjf


/**
 * <p>
 *     Integer to character and vice-versa
 * </p>
 *  
 */
public class TinyUrl {

    private final String characterMap = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    private final int charBase = characterMap.length();

    public String covertToCharacter(int num){
        StringBuilder sb = new StringBuilder();

        while (num > 0){
            sb.append(characterMap.charAt(num % charBase));
            num /= charBase;
        }

        return sb.reverse().toString();
    }

    public int covertToInteger(String str){
        int num = 0;
        for(int i = 0 ; i< str.length(); i++)
            num += characterMap.indexOf(str.charAt(i)) * Math.pow(charBase , (str.length() - (i + 1)));

        return num;
    }
}

class TinyUrlTest{

    public static void main(String[] args) {
        TinyUrl tinyUrl = new TinyUrl();
        int num = 122312215;
        String url = tinyUrl.covertToCharacter(num);
        System.out.println("Tiny url:  " + url);
        System.out.println("Id: " + tinyUrl.covertToInteger(url));
    }
}

Scala에서의 구현 :

class Encoder(alphabet: String) extends (Long => String) {

  val Base = alphabet.size

  override def apply(number: Long) = {
    def encode(current: Long): List[Int] = {
      if (current == 0) Nil
      else (current % Base).toInt :: encode(current / Base)
    }
    encode(number).reverse
      .map(current => alphabet.charAt(current)).mkString
  }
}

class Decoder(alphabet: String) extends (String => Long) {

  val Base = alphabet.size

  override def apply(string: String) = {
    def decode(current: Long, encodedPart: String): Long = {
      if (encodedPart.size == 0) current
      else decode(current * Base + alphabet.indexOf(encodedPart.head),encodedPart.tail)
    }
    decode(0,string)
  }
}

Scala 테스트를 사용한 테스트 예 :

import org.scalatest.{FlatSpec, Matchers}

class DecoderAndEncoderTest extends FlatSpec with Matchers {

  val Alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"

  "A number with base 10" should "be correctly encoded into base 62 string" in {
    val encoder = new Encoder(Alphabet)
    encoder(127) should be ("cd")
    encoder(543513414) should be ("KWGPy")
  }

  "A base 62 string" should "be correctly decoded into a number with base 10" in {
    val decoder = new Decoder(Alphabet)
    decoder("cd") should be (127)
    decoder("KWGPy") should be (543513414)
  }

}

Xeoncross 클래스 기반 기능

function shortly($input){
$dictionary = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','0','1','2','3','4','5','6','7','8','9'];
if($input===0)
    return $dictionary[0];
$base = count($dictionary);
if(is_numeric($input)){
    $result = [];
    while($input > 0){
        $result[] = $dictionary[($input % $base)];
        $input = floor($input / $base);
    }
    return join("", array_reverse($result));
}
$i = 0;
$input = str_split($input);
foreach($input as $char){
    $pos = array_search($char, $dictionary);
    $i = $i * $base + $pos;
}
return $i;
}

다음은 bit.ly 일 가능성이있는 Node.js 구현입니다. 매우 임의의 7 자 문자열을 생성합니다.

Node.js 암호화를 사용하여 7 개의 문자를 무작위로 선택하는 대신 매우 임의의 25 자 세트를 생성합니다.

var crypto = require("crypto");
exports.shortURL = new function () {
    this.getShortURL = function () {
        var sURL = '',
            _rand = crypto.randomBytes(25).toString('hex'),
            _base = _rand.length;
        for (var i = 0; i < 7; i++)
            sURL += _rand.charAt(Math.floor(Math.random() * _rand.length));
        return sURL;
    };
}

내 Python 3 버전

base_list = list("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
base = len(base_list)

def encode(num: int):
    result = []
    if num == 0:
        result.append(base_list[0])

    while num > 0:
        result.append(base_list[num % base])
        num //= base

    print("".join(reversed(result)))

def decode(code: str):
    num = 0
    code_list = list(code)
    for index, code in enumerate(reversed(code_list)):
        num += base_list.index(code) * base ** index
    print(num)

if __name__ == '__main__':
    encode(341413134141)
    decode("60FoItT")

양질의 Node.js / JavaScript 솔루션에 대해서는 철저하게 테스트되고 몇 달 동안 프로덕션에 사용 된 id-shortener 모듈을 참조하십시오 .

기본적으로 Redis를 사용 하는 플러그 형 스토리지에 의해 지원되는 효율적인 ID / URL 단축기를 제공하며 단축 ID 문자 집합을 사용자 정의하고 단축이 멱 등성 인지 여부를 사용자 정의 할 수도 있습니다 . 이것은 모든 URL 단축기가 고려되지 않는 중요한 차이점입니다.

여기의 다른 답변과 관련 하여이 모듈은 위에서 Marcel Jackwerth의 우수한 답변을 구현합니다.

솔루션의 핵심은 다음 Redis Lua 스 니펫에서 제공합니다 .

local sequence = redis.call('incr', KEYS[1])

local chars = '0123456789ABCDEFGHJKLMNPQRSTUVWXYZ_abcdefghijkmnopqrstuvwxyz'
local remaining = sequence
local slug = ''

while (remaining > 0) do
  local d = (remaining % 60)
  local character = string.sub(chars, d + 1, d + 1)

  slug = character .. slug
  remaining = (remaining - d) / 60
end

redis.call('hset', KEYS[2], slug, ARGV[1])

return slug

참고 URL : https://stackoverflow.com/questions/742013/how-do-i-create-a-url-shortener

반응형