Example #1
0
def generate_short_url(original_url):
    """
    Sharding is a must if this TinyUrlService need to support high concurrency
    :param original_url: 
    :return: 
    """
    session = DBSession()
    short_url_in_db = session.query(ShortUrl).filter(
        ShortUrl.original_url == original_url).first()
    if short_url_in_db:
        short_id = short_url_in_db.id
        hash_str = utils.encode_base64(short_id)
        return hash_str

    short_url = ShortUrl()
    short_url.original_url = original_url
    current = datetime.datetime.now()
    short_url.createdTime = current
    short_url.updatedTime = current
    try:
        session.add(short_url)
        session.commit()
        short_id = short_url.id
        hash_str = utils.encode_base64(short_id)
        session.query(ShortUrl).filter(ShortUrl.id == short_id).update(
            {"short_url": hash_str})
        session.commit()
        session.close()
        return hash_str
    except Exception as e:
        logging.error('ERROR generate_short_url url:%s,error:%s' %
                      (original_url, e))
Example #2
0
    def test_when_user_has_many_urls_created(self):
        login_user(self.client, self.user)
        ShortUrl(original_url='http://test.pl',
                 slug='test',
                 user_id=str(self.user.id)).save()
        ShortUrl(original_url='http://test2.pl',
                 slug='test2',
                 user_id=str(self.user.id)).save()

        response = self.client.get(self.ENDPOINT)

        self.assertEqual(
            response.json, {
                'URLs': [{
                    'slug': 'test',
                    'original_url': 'http://test.pl',
                    'created': '2017-02-01T12:00:00+00:00',
                    'access_counter': 0
                }, {
                    'slug': 'test2',
                    'original_url': 'http://test2.pl',
                    'created': '2017-02-01T12:00:00+00:00',
                    'access_counter': 0
                }]
            })
Example #3
0
    def test_when_duplicated_slug_in_db(self):
        slug = 'test'
        ShortUrl(original_url='http://test.pl', slug=slug).save()
        ShortUrl(original_url='http://test2.pl', slug=slug).save()

        response = self.client.get(self.ENDPOINT_TEMPLATE.format(slug))

        self.assertEqual(response.status_code, 500)
Example #4
0
def generate_short_url():
    """
    .. :quickref: ShortUrl; Generate short url.

    Generate short url for original url given by user using custom slug if specified.

    :reqheader Accept: application/json
    :<json string original_url: url of website to be shorten
    :<json string slug: (optional) slug to use in shortened url

    :resheader Content-Type: application/json
    :>json string short_url: short url which redirects to original url

    :status 201: ShortUrl created
    :status 500: slug already exists in db
    """
    url_data = RegisterUrlSchema().load(request.get_json()).data
    url_data['user_id'] = str(current_user.id)
    short_url_obj = ShortUrl(**url_data)

    if 'slug' in url_data:
        if ShortUrl.objects(slug=short_url_obj.slug):
            log.error('Slug already exists in database')
            raise SlugAlreadyExistsException()
    else:
        slug = generate_random_slug(length=6)
        while ShortUrl.objects(slug=slug):
            log.warning('Slug duplicate detected! - {}'.format(slug))
            slug = generate_random_slug(length=6)
        short_url_obj.slug = slug
    short_url_obj.save()
    short_url = url_for('main.get_url',
                        slug=short_url_obj.slug,
                        _external=True)
    return make_response(jsonify(dict(short_url=short_url)), CREATED)
Example #5
0
 def long2short(self, request):
     if request.method == 'POST':
         url = request.POST.get('url')
         user_id = request.POST.get('userId')
         is_good = utils.is_good_url(url)
         # 检查url
         if not is_good:
             return mhttp.params_error(message='URL不合法')
         # 检查url是否已经生成过
         objs = ShortUrl.objects.all().filter(url=url,
                                              is_active=True,
                                              user=user_id,
                                              is_delete=False)
         if len(objs) > 0:
             return mhttp.result(
                 data={
                     'url': constant.shorturl_prefix + objs[0].short_code
                 })
         # 生成短码
         while True:
             short_code = utils.random_str(size=4)
             objs = ShortUrl.objects.all().filter(short_code=short_code,
                                                  is_active=True)
             if len(objs) == 0:
                 break
         # 存储
         shortUrl = ShortUrl()
         shortUrl.url = url
         shortUrl.short_code = short_code
         shortUrl.user = User.objects.get(id=user_id)
         shortUrl.save()
         return mhttp.result(
             data={'url': constant.shorturl_prefix + short_code})
Example #6
0
    def test_when_non_unique_slug_specified(self):
        login_user(self.client, self.user)
        new_user = User()
        new_user.save()
        ShortUrl(original_url='http://test.pl',
                 slug='test_slug',
                 user_id=str(new_user.id)).save()
        url_data = dict(original_url='http://destination.pl', slug='test_slug')

        response = self.client.post(self.ENDPOINT, data=url_data)

        self.assertEqual(response.status_code, 500)
        short_links = ShortUrl.objects()
        self.assertEqual(len(short_links), 1)
        short_link = short_links[0]
        self.assertEqual(short_link.original_url, 'http://test.pl')
        self.assertEqual(short_link.user_id, str(new_user.id))
        self.assertEqual(short_link.slug, 'test_slug')
Example #7
0
    def test_when_slug_in_db(self):
        slug = 'test'
        ShortUrl(original_url='http://test.pl', slug=slug,
                 access_counter=0).save()

        response = self.client.get(self.ENDPOINT_TEMPLATE.format(slug))

        short_url = ShortUrl.objects.get(slug=slug)
        self.assertEqual(short_url.access_counter, 1)
        self.assertEqual(response.status_code, 302)
        self.assertEqual(response.headers['location'], 'http://test.pl')
Example #8
0
    def test_when_slug_in_db_but_other_user_is_slug_owner(self):
        login_user(self.client, self.user)
        other_user = User()
        other_user.save()
        slug = 'test'
        ShortUrl(original_url='http://test.pl',
                 slug=slug,
                 user_id=str(other_user.id)).save()

        response = self.client.get(self.ENDPOINT_TEMPLATE.format(slug))

        self.assertEqual(response.status_code, 401)
Example #9
0
def get_list_of_user_urls():
    """
    .. :quickref: ShortUrl; Get info about user`s short urls.

    Return details about short urls generated by current user.

    :resheader Content-Type: application/json
    :>json list[url_info] URLs: list of dicts with details about short url

    :status 200: query to database succeeded
    """
    short_links = ShortUrl.objects(user_id=str(current_user.id))
    return jsonify({'URLs': ShortUrlSchema(many=True).dump(short_links).data})
Example #10
0
def get_url(slug):
    """
    .. :quickref: ShortUrl; Get original url.

    Redirect to original url for given slug.

    :param slug: short string which was created during generation short url

    :status 302: ShortUrl for given slug found and redirect is performed
    :status 404: ShortUrl for given slug not found
    :status 500: multiple ShortUrls for given slug found
    """
    try:
        # FIXME: update can raise different exceptions
        ShortUrl.objects(slug=slug).update(inc__access_counter=1)
        short_link = ShortUrl.objects.get(slug=slug)
        return redirect(short_link.original_url)
    except DoesNotExist as e:
        log.error(e)
        raise NotFound()
    except MultipleObjectsReturned as e:
        log.error(e)
        raise InternalServerError()
Example #11
0
    def test_when_only_original_url_specified_and_generated_slug_already_exist(
            self, generate_random_slug_mock):
        login_user(self.client, self.user)
        generate_random_slug_mock.side_effect = ['test_slug', 'new_slug']
        ShortUrl(original_url='http://test.pl', slug='test_slug').save()
        url_data = dict(original_url='http://destination.pl')

        short_links = ShortUrl.objects()
        self.assertEqual(len(short_links), 1)

        response = self.client.post(self.ENDPOINT, data=url_data)

        self.assertEqual(response.status_code, 201)
        self.assertDictEqual(response.json,
                             dict(short_url='http://localhost:5001/new_slug'))
        short_links = ShortUrl.objects(slug__ne='test_slug')
        self.assertEqual(len(short_links), 1)
        short_link = short_links[0]
        self.assertEqual(short_link.original_url, 'http://destination.pl')
        self.assertEqual(short_link.slug, 'new_slug')
        self.assertEqual(short_link.user_id, str(self.user.id))
        self.assertEqual(short_link.access_counter, 0)
        self.assertEqual(short_link.created,
                         datetime.datetime(2017, 2, 1, 12, 0, tzinfo=tzutc()))
Example #12
0
    def test_when_unique_slug_specified(self):
        login_user(self.client, self.user)
        url_data = dict(original_url='http://destination.pl', slug='test_slug')

        response = self.client.post(self.ENDPOINT, data=url_data)

        self.assertEqual(response.status_code, 201)
        self.assertDictEqual(response.json,
                             dict(short_url='http://localhost:5001/test_slug'))
        short_links = ShortUrl.objects()
        self.assertEqual(len(short_links), 1)
        short_link = short_links[0]
        self.assertEqual(short_link.original_url, 'http://destination.pl')
        self.assertEqual(short_link.slug, 'test_slug')
        self.assertEqual(short_link.user_id, str(self.user.id))
        self.assertEqual(short_link.access_counter, 0)
        self.assertEqual(short_link.created,
                         datetime.datetime(2017, 2, 1, 12, 0, tzinfo=tzutc()))
Example #13
0
def index():
    form = UrlForm()
    # Does all of the form processing work.
    # Returns true if nothing went wrong retrieving the data.
    if form.validate_on_submit(): 
        if is_valid_url(form.url.data):
            shortlink = generate_shortlink()
            shorturl = ShortUrl(shortlink=shortlink, link=form.url.data)
            db.session.add(shorturl)
            db.session.commit()
       
            flash('Request to shorten URL {}'.format(form.url.data))
            flash('At extension {}'.format(shortlink))
            return redirect(url_for('results', link=shortlink))
        else:
            flash('Request to shorten URL {} failed'.format(form.url.data))
            return redirect(url_for('results'))

    return render_template('index.html', form=form)
Example #14
0
    def test_when_slug_in_db_and_user_is_its_owner(self):
        login_user(self.client, self.user)
        slug = 'test'
        ShortUrl(
            original_url='http://test.pl',
            slug=slug,
            user_id=str(self.user.id),
        ).save()

        response = self.client.get(self.ENDPOINT_TEMPLATE.format(slug))
        response.json['created'] = parser.parse(response.json['created'])

        self.assertEqual(response.status_code, 200)
        self.assertDictEqual(
            response.json,
            dict(original_url='http://test.pl',
                 created=datetime.datetime(2017,
                                           2,
                                           1,
                                           12,
                                           0,
                                           0,
                                           tzinfo=tzutc()),
                 access_counter=0))