over 1 year ago

I was running a django app on a linux machine and when I tried to login to the admin page, I kept getting redirected to the login page itself. It looks like this:

  1. POST /login/ 302
  2. GET / 302 < - should give me a 200 single I have logged in successfully but returns 302 instead
  3. GET ?next=/ 200 <- back to login page again

The site works when I use ./manage runserver but it wouldn't work when I use gunicorn to run it. I clear the cookie but it didn't work. I tried to set debug = False didn't work either. Eventially I found the problem, I wanted to use the database to store sessions, so I did this:

INSTALLED_APPS = (
    ...,
    django.contrib.sessions
)

SESSION_ENGIN = 'django.contrib.sessions.backends.cache'

For some reason, my session cache is messed up and I have to use this setting instead:

SESSION_ENGIN = 'django.contrib.sessions.backends.cached_db'

Instead of storing cache in memory which disappears after server restart, cached_db writes it to the database. I have used the cache option before and worked but not this time.

 
over 1 year ago

I had the pleasure of setting up my own pypi server last week because the server I had to work with is behind a corporate firewall.

To setup your own pypi server, here is what to do:

  1. Download pypiserver, then:
unzip pypiserver-1.1.10
cd pypiserver-1.1.10
python setup.py install

Config pypyserver settings:

cd ~
touch .pypirc

Enter the following info in to .pypirc:

[distutils]
index-servers =
  pypi
  local

[pypi]
username:
password:

[local]
repository: http://localhost:8080
username:
password: 

Setup the packages dir, this is the place where you store the packages:

cd ~
mkdir packages

Run!

pypi-server -p 8080 ~/packages

You might want to keep the server running even after you logout of terminal:

nohup pypi-server -p 8080 ~/packages &

You need to stuff your packages folder so that there will be something for pip install, here are essential packages you need to at least get a virtual environment running:

  • pbr
  • pip
  • setuptools
  • six
  • stevedore
  • virtualenv
  • virtualenv-clone
  • virtualenvwrapper
  • wheel

To download these packages, just go to https://pypi.python.org/pypi/ and search for the package name, then download the tar.gz version of that package. Once downloaded, move the zip file to the ~/packages folder.

To verify that the server is up and running, simply go to localhost:8080/simple/, you should see a list of package names (or empty if you haven't copied any packages into the packages folder yet).

Config your client to download python packages from your server:

cd ~
mkdir .pip
touch .pip/pip.conf

Put the following lines into pip.conf

[global]
index-url = http://localhost:8080/simple
[install]
trusted-host = localhost

Done! Try using pip install and it will download a package instantly from your ~/packages folder and install it :)

 
over 1 year ago

Found an excellent snippet here by monikkinom, which compresses all uploaded images to jpg before saving to disk:

from PIL import Image as Img
import StringIO

class Images(models.Model):
    image = models.ImageField()

    def save(self, *args, **kwargs):
        if self.image:
            img = Img.open(StringIO.StringIO(self.image.read()))
            if img.mode != 'RGB':
                img = img.convert('RGB')
            img.thumbnail((self.image.width/1.5,self.image.height/1.5), Img.ANTIALIAS)
            output = StringIO.StringIO()
            img.save(output, format='JPEG', quality=70)
            output.seek(0)
            self.image= InMemoryUploadedFile(output,'ImageField', "%s.jpg" %self.image.name.split('.')[0], 'image/jpeg', output.len, None)
        super(Images, self).save(*args, **kwargs)

According to the official doc, the parameters for the InMemoryUploadedFile are:

file, field_name, name, content_type, size, charset, content_type_extra=None

Bonus

If you want to scale the image and still keeps its aspect ratio:

new_width = 800
img.thumbnail((new_wdith, new_width * self.image.height / self.image.width), Img.ANTIALIAS)
 
over 1 year ago

To understand the concept of iterator in Javascript, it is important to memorize the following three protocal:

1. Mark an object iterable

To mark an object iterable, you need to add a Symbol.iterator property to it:

var obj = {};
obj[Symbol.iterator] = function() { return iteratorObject; }

The Symbol.iterator part looks really odd if you don't know what Symbol is all about. One way to think about it is to see it as metadata that describes the hidden behaviors of an object. When an object is marked with the iterator symbol, it means you can loop through it like an array.

2. Return an iterator object

The code snippet above returns an iterator object. An iterator object needs to have a next method which is a function that returns an iterator result object:

iteratorObject = {
    next: function(){
        return iteratorResultObj;
    }
}

3. Return an iterator result object

Finally, I mean finally we can return some real values rather than wrappers that conforms to the iterable and iterator protocal.The iterator result object has to have two properties, one named value and the other named done.

iteratorResultObj = {
  value: ...,
  done: ...  // either true or false

}

As long as an object has the three traits explained above, it is iterable and can be used in a for...of loop or being spreaded [...myObj].

Putting it all together

var obj = {};

obj[Symbol.iterator] = function (){  // mark an object as iterable

  var i = 1;
  return {    // this is the iterator object

    next: function(){
      return i < 5 ? 
      {  // this is the iterator result object

        value: i++,
        done: false
      } : { done: true } // when the iterator reaches the end, value = undefined and done = true

    }
  }
}

var iter = obj[Symbol.iterator]();
console.log('value: ' + iter.next().value);
console.log('value: ' + iter.next().value);
console.log('value: ' + iter.next().value);
console.log('value: ' + iter.next().value);
console.log('done: ' + iter.next().done);

// the code above is equivalent of the following loop

for(var j of obj){
  console.log(j);
}

Here is a jsbin link of the code above.

Bonus

To use ES6 syntax and define an iterator within a class:

class MyArray {
    constructor(...items) {
        this.items = items;
    }

    [Symbol.iterator]() {
      let pos = 0;
      let data = this.items; // the value of `this` changes to undefined inside the next() function below, thus, we need to store it in a variable first

      return {
        next: () => {
            return pos < data.length? 
              { value: data[pos++], done: false } 
            : { done: true }
        }
      }
    }
}

let arr = new MyArray(1,2,3)

for(const i of arr){
  console.log(i);
}

jsbin link

 
over 1 year ago

The HTTP 1.1 specification states:

A single-user client SHOULD NOT maintain more than 2 connections with any server or proxy.

But many modern browsers supports more than that:

IE 6 and 7:      2
IE 8:            6
IE 9:            6
IE 10:           8
IE 11:           8
Firefox 2:       2
Firefox 3:       6
Firefox 4 to 17: 6
Opera 9.63:      4
Opera 10:        8
Opera 11 and 12: 6
Chrome 1 and 2:  6
Chrome 3:        4
Chrome 4 to 23:  6
Safari 3 and 4:  4

The connection limitation is per hostname not IP address. [1]

Thus, even a.test.com and b.test.com points to the same ip address, you can still double the number of parrallel connections.

source: http://stackoverflow.com/questions/985431/max-parallel-http-connections-in-a-browser

 
over 1 year ago

On Ubuntu 14.04, the conifg file for sshd is located at:

/etc/ssh/sshd_config

Before making any modification, make a copy of the original config and make it read-only:

sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.factory-defaults
sudo chmod a-w /etc/ssh/sshd_config.factory-defaults

Then, open up sshd_config and modify the following lines:

LogLevel VERBOSE # also logs failed attempts, the log file can be found at /var/log/auth.log

AllowUsers user1 user2@10.0.0.1 # only allow user1 and user2 from 10.0.0.1 for example

PasswordAuthentication no # disable password login, use public key login instead

AllowTcpForwarding no # do not allow forwarding

X11Forwarding no

Restart ssh service to make the new config effective:

sudo service ssh restart

To limit the number of login attempts during a time period, enable the Uncomplicated Firewall by:

sudo ufw enable

Then, limit the number of ssh login attempts within 30 seconds to be 10 tries. More attempts will be dropped by issuing this command:

sudo ufw limit ssh

How to config your client

Once the server config has taken effect, you need to update your client ssh config which is found at ~/.ssh/config on your computer.

Host tinBox
HostName 11.12.13.14
User root
PubKeyAuthentication Yes
IdentityFile ~/.ssh/private_key

Make sure PubKeyAuthentication and a absolute/relative path to the private_key are added.

 
over 1 year ago

I work on a Ubuntu (14.04) machine with Postgres 9.4 installed. The config file directory of Postgres is located at:

/etc/postgresql/9.4/main/postgresql.conf

Inside the config file, uncomment and adjust the following lines:

log_destination = 'stderr, csvlog'  # save logs as .log file and a .csv file

logging_collector = on # required to be on for csvlogs

log_directory = '/var/log/postgresql' # use any directory the postgres user have read and write access to. /var/log/postgresql is a pretty good place to start with

log_filename = 'postgresql-%Y-%m-%d_%H%M.log' # modify the %modifiers to suit your need

log_truncate_on_rotation = on # should logs be saved in separated files instead of one gigantic file

log_rotation_age = 1d # save the logs into a new file everyday. If you'd rather seperate files based on file size, modify log_rotation_size instead of this one

log_line_prefix = '%t [%p-%l] %q%u@%d ' # what information should each line of logs include

log_statement = 'all' # check out here for more info: http://www.postgresql.org/docs/9.4/static/runtime-config-logging.html#GUC-LOG-STATEMENT

log_timezone = 'Asia/Shanghai' # what timezone should be used for timestamp each log

These are the basic options I enabled, and to make this new change effective immediately, restart postgres by:

sudo service postgresql restart

For more config explanation, check the official doc here

 
over 1 year ago

I use eslint to lint ES2015 + React projects. One problem I encounter with eslint is that it does not support the spread operator. I realized that I had to install babel-eslint to make this work. I have to modify .eslintrc to make it work with babel-eslint:

{
  "parser": "babel-eslint",
    ...
}

Then, I run eslint and got this error:

Error: Cannot find module 'estraverse-fb'

It turns out that if you are using eslint 2.0, you have to use babel-eslint 6.x.x. The detail is explained in this thread.

 
over 1 year ago

I was learning eslint's react/jsx options and stumbled upon this rule react/jsx-no-bind:

A bind call or arrow function in a JSX prop will create a brand new function on every single render. This is bad for performance, as it will result in the garbage collector being invoked way more than is necessary.

The following patterns are considered warnings:

<div onClick={this._handleClick.bind(this)}></div>

<div onClick={() => console.log('Hello!'))}></div>

The following patterns are not considered warnings:

<div onClick={this._handleClick}></div>
 
over 1 year ago

When writting React using the ES6 class syntax like this:

class MyClass extends React.component {
    constructor(){
        super()
    }
}

Two questions may arise:

  1. Is it necessary to call super() inside constructor?
  2. What is the difference between callling super() and super(props)?

Answer #1

Always call super() if you have a constructor and don't worry about it if you don't have a constructor

Calling super() is necessary only if you need to have a constructor. Take a look at this code:

class MyClass extends React.component {
    render(){
        return <div>Hello { this.props.world }</div>;
    }
}

The code above is perfectly valid. You don't have to call super() for every react component you create. However, if there is a constructor in your code, then you MUST call super:

class MyClass extends React.component {
    constructor(){
        console.log(this) //Error: 'this' is not allowed before super()

    }
}

The reason why this cannot be allowed before super() is because this is uninitialized if super() is not called [1]

You may think you can get away with an empty constructor without callling super():

class MyClass extends React.component {
    constructor(){} // Error: missing super() call in constructor

}

ES6 class constructors MUST call super if they are subclasses. Thus, you have to call super() as long as you have a constructor. (But a subclass does not have to have a constructor)

Answer #2

Call super(props) only if you want to access this.props inside the constructor. React automatically set it for you if you want to access it anywhere else.

The effect of passing props when calling super() allows you to access this.props in the constructor:

class MyClass extends React.component{
    constructor(props){
        super();
        console.log(this.props); // this.props is undefined

    }
}

To fix it:

class MyClass extends React.component{
    constructor(props){
        super(props);
        console.log(this.props); // prints out whatever is inside props

    }
}

There is no need to pass props into the constructor if you want to use it in other places. Because React automatically set it for you [2]

class MyClass extends React.component{
    render(){
        // There is no need to call `super(props)` or even having a constructor 

        // this.props is automatically set for you by React 

        // not just in render but another where else other than the constructor

        console.log(this.props);  // it works!

    }
}