| 71 | | |
| | 71 | |
| | 72 | class MIMETypes(object): |
| | 73 | """MIMETypes registration mapping |
| | 74 | |
| | 75 | The MIMETypes object class provides a single point to hold onto all |
| | 76 | the registered mimetypes, and their association extensions. It's |
| | 77 | used by the mimetypes function to determine the appropriat content |
| | 78 | type to return to a client. |
| | 79 | |
| | 80 | """ |
| | 81 | extension_mapping = {} |
| | 82 | type_mapping = {} |
| | 83 | |
| | 84 | def load_defaults(cls): |
| | 85 | """Loads a default mapping of extensions and mimetypes |
| | 86 | |
| | 87 | These are suitable for most web applications by default. |
| | 88 | Additional types can be added with the MIMETypes.register |
| | 89 | method. |
| | 90 | |
| | 91 | """ |
| | 92 | extension_mapping = {} |
| | 93 | type_mapping = {} |
| | 94 | mimetypes.init() |
| | 95 | for ext, mimetype in mimetypes.types_map.iteritems(): |
| | 96 | type_mapping[mimetype] = ext[1:] |
| | 97 | extension_mapping[ext[1:]] = mimetype |
| | 98 | cls.extension_mapping.update(extension_mapping) |
| | 99 | cls.type_mapping.update(type_mapping) |
| | 100 | |
| | 101 | # Add some common defaults and aliases |
| | 102 | MIMETypes.register('*/*', 'all') |
| | 103 | MIMETypes.register('text/plain', 'text', ext_aliases=('txt',)) |
| | 104 | MIMETypes.register('text/html', 'html', |
| | 105 | type_aliases=('application/xhtml+xml',), |
| | 106 | ext_aliases=('xhtml',)) |
| | 107 | MIMETypes.register('text/javascript', 'js', |
| | 108 | type_aliases=('application/javascript', |
| | 109 | 'application/x-javascript')) |
| | 110 | MIMETypes.register('text/css', 'css') |
| | 111 | MIMETypes.register('text/calendar', 'ics') |
| | 112 | MIMETypes.register('text/csv', 'csv') |
| | 113 | MIMETypes.register('application/xml', 'xml', |
| | 114 | type_aliases=('text/xml', 'application/x-xml')) |
| | 115 | MIMETypes.register('application/rss+xml', 'rss') |
| | 116 | MIMETypes.register('application/atom+xml', 'atom') |
| | 117 | MIMETypes.register('application/x-yaml', 'yaml', |
| | 118 | type_aliases=('text/yaml',)) |
| | 119 | MIMETypes.register('multipart/form-data', 'multipart_form') |
| | 120 | MIMETypes.register('application/x-www-form-urlencoded', 'url_encoded_form') |
| | 121 | MIMETypes.register('application/json', 'json', |
| | 122 | type_aliases=('text/x-json',)) |
| | 123 | load_defaults = classmethod(load_defaults) |
| | 124 | |
| | 125 | def register(cls, mimetype, extension, type_aliases=None, ext_aliases=None): |
| | 126 | """Register additional MIMETypes |
| | 127 | |
| | 128 | Additional mimetypes that a user wants to recognize and handle |
| | 129 | should be registered using this method. Extension aliases that |
| | 130 | should be treated as equivilant to the desired extension, along |
| | 131 | with alias mimetypes can also be registered. |
| | 132 | |
| | 133 | Example: |
| | 134 | # Register text/plain as the text extension, or txt |
| | 135 | MIMETypes.register('text/plain', 'text', ext_aliases=('txt',)) |
| | 136 | |
| | 137 | """ |
| | 138 | cls.type_mapping[mimetype] = extension |
| | 139 | if type_aliases: |
| | 140 | for alias in type_aliases: |
| | 141 | cls.type_mapping[alias] = extension |
| | 142 | |
| | 143 | cls.extension_mapping[extension] = mimetype |
| | 144 | if ext_aliases: |
| | 145 | for alias in ext_aliases: |
| | 146 | cls.extension_mapping[alias] = mimetype |
| | 147 | register = classmethod(register) |
| | 148 | |
| | 149 | |
| | 150 | def mimetype(extension): |
| | 151 | """Check the Routes match and client HTTP Accept to attempt to use |
| | 152 | the appropriate mime-type |
| | 153 | |
| | 154 | This works best with Routes ``map.resource`` which sets up routes |
| | 155 | that can accept matches with a specific extension. |
| | 156 | |
| | 157 | Example: |
| | 158 | def somaction(self): |
| | 159 | # prepare a bunch of data |
| | 160 | # ...... |
| | 161 | |
| | 162 | if mimetype('html'): |
| | 163 | return render('/some/template.html') |
| | 164 | elif mimetype('atom'): |
| | 165 | return render('/some/xml_template.xml') |
| | 166 | elif mimetype('csv'): |
| | 167 | # write the data to a csv file |
| | 168 | return csvfile |
| | 169 | else: |
| | 170 | abort(404) |
| | 171 | |
| | 172 | """ |
| | 173 | request = pylons.request._current_obj() |
| | 174 | # Pull out the possible return content-type |
| | 175 | return_type = MIMETypes.extension_mapping.get(extension) |
| | 176 | if not return_type: |
| | 177 | raise Exception("Can't check for extensions that haven't been " |
| | 178 | "registered") |
| | 179 | |
| | 180 | # Check for a format in Route args first |
| | 181 | route_format = request.environ['pylons.routes_dict'].get('format') |
| | 182 | if route_format: |
| | 183 | mime_type = MIMETypes.extension_mapping[route_format] |
| | 184 | resolved_extension = MIMETypes.type_mapping[mime_type] |
| | 185 | if resolved_extension == extension: |
| | 186 | pylons.response.headers['Content-Type'] = mime_type |
| | 187 | return True |
| | 188 | |
| | 189 | # Check to see if this matches in the Request accept |
| | 190 | if return_type in request.accept_language: |
| | 191 | pylons.response.headers['Content-Type'] = return_type |
| | 192 | return True |
| | 193 | |
| | 194 | # Didn't match the route format or the Request accept, don't match |
| | 195 | return False |
| | 196 | |
| | 197 | |