1

Currently I am exposing a Django application (for the momento is just thier users schema) with Django Rest Framework and happen that each serialized model, in the url attribute, I have is the localhost machine address development and don't take the hostname of my production server machine which is located in amazon like as EC2 instance

In this picture can detailed it.

enter image description here

How to make for the url of each model that I've serialized take the hostname of the production machine in which the application is deployed? In this case, an amazon ec2 instance ...

These are my serialized models userprofiles/serializers.py

from django.contrib.auth.models import Group
from .models import User, PlayerProfile, CoachProfile, ViewerProfile
from rest_framework import serializers

# Serializers define the API representation
# Exponse the model and their fields
class UserSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = User
        fields = ('url','id', 'username', 'password','first_name','last_name','email','is_active',
                  'is_staff','is_superuser','last_login','date_joined','is_player','is_coach',
                  'is_viewer','photo',)

class GroupSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Group
        fields = ('url', 'name')


class PlayerProfileSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = PlayerProfile
        fields = ('url', 'user','full_name','position',)

class CoachProfileSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = CoachProfile
        fields = ('url', 'user','full_name',)

class ViewerProfileSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = ViewerProfile
        fields = ('url', 'user','full_name','specialty')

This is my urls.py global file (not belont to userprofiles application that contain all the serialized models.)

from django.conf.urls import url, include
from django.contrib import admin

from .views import home, home_files

from rest_framework import routers
from userprofiles import views

# Router provide an easy way of automatically determining the URL conf
router = routers.DefaultRouter()
router.register(r'users', views.UserViewSet)
router.register(r'groups', views.GroupViewSet)
router.register(r'players', views.PlayerProfileViewSet)
router.register(r'coachs', views.CoachProfileViewSet)
router.register(r'views', views.ViewerProfileViewSet)


urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^$', home, name='home'),

    url(r'^(?P<filename>(robots.txt)|(humans.txt))$',
        home_files, name='home-files'),

    # Wire up our API using automatic URL routing.
    url(r'^api/v1/', include(router.urls)),

    # If you're intending to use the browsable API you'll probably also want to add REST framework's
    # login and logout views.
    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
] 

And this is my userprofiles/views.py file in where I have expose the models serializeds

from django.shortcuts import render
from django.contrib.auth.models import Group
from .models import User, PlayerProfile, CoachProfile, ViewerProfile

from rest_framework import viewsets
from .serializers import UserSerializer, GroupSerializer, PlayerProfileSerializer, CoachProfileSerializer, ViewerProfileSerializer

# Create your views here.

# Viewsets define the behavior of the view
class UserViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows users to be viewed or edited.
    """
    queryset = User.objects.all().order_by('-date_joined')
    serializer_class = UserSerializer

class GroupViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows groups to be viewed or edited.
    """
    queryset = Group.objects.all()
    serializer_class = GroupSerializer

class PlayerProfileViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows players to be viewed or edited.
    """
    queryset = PlayerProfile.objects.all()
    serializer_class = PlayerProfileSerializer

class CoachProfileViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows coachs to be viewed or edited.
    """
    queryset = CoachProfile.objects.all()
    serializer_class = CoachProfileSerializer

class ViewerProfileViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows viewers to be viewed or edited.
    """
    queryset = ViewerProfile.objects.all()
    serializer_class = ViewerProfileSerializer

Any orientation or support about it, I will be grateful :)

bgarcial
  • 2,915
  • 10
  • 56
  • 123
  • 1
    What http server are you using? In nginx case `proxy_set_header` really helped me. Usage examples from [documentation](https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/) and [similar case](https://stackoverflow.com/questions/39715510/nginx-when-to-use-proxy-set-header-host-host-vs-proxy-host) – Trigremm Sep 11 '22 at 09:15

1 Answers1

1

I think what you're trying to do is have: "http://127.0.0.1" be replace with "http://ec2-52-..." - your instance's current DNS name.

You can't get this data on the instance level (ie. via some command) as the DNS name is stored on Amazon's DNS servers outside of your instance. You can however retrieve this info using the EC2 Instance meta-data service and retrieve the public-hostname field by sending a HTTP request to http://169.254.169.254/latest/meta-data/public-hostname from your instance.

However, this mightn't be a good idea if you have to do this for every REST communication. Maybe you could cache it?

This use case seems weird to me. If a node was submitting a REST request to this instance, it would already know it's DNS name.... So why are you responding with it again? I don't know your use case so I could be totally off the mark here, but I hope this helps!!

mickzer
  • 5,958
  • 5
  • 34
  • 57
  • thanks for their support. I also feel weird this case, because the url should will be take the hostname of my production server of a transparent way not? The metadata instance service seem a good alternative, but make this quey in each communication REST is expensive really? I don't know that can be happened – bgarcial Feb 23 '16 at 13:37
  • 1
    You can't get the external DNS name reliably without querying the meta data. You could use an elastic IP and that should keep the DNS name static between start/stops but I don't think this is reliable. Yes, it could potentially be expensive. Wouldn't you just return relative paths eg /api/v1/users – mickzer Feb 23 '16 at 16:12
  • I think that my problem is in that I am using a file for start my gunicorn server such as say this tutorial https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-django-with-postgres-nginx-and-gunicorn (view Step nine gunicorn_config.py) in the bind directive `bind = '127.0.0.1:8001'` I am fixing this in my deployment files inside my amazon EC2 and view the results ... – bgarcial Feb 23 '16 at 16:20
  • This won't change the DNS name to what you desire. You need to understand that the DNS name for your instance is recorded on a DNS server outside of your instance. ie. On amazon's DNS server. It just maps the DNS name to your instance's IP. So your instance doesn't know about it. – mickzer Feb 23 '16 at 16:27
  • Of course, I understand. But in this case when I start my gunicorn server with localhost address, this does not make that my urls (serialized models) appear with this localhost address? Or in negative case, what is the best solution? – bgarcial Feb 23 '16 at 16:40